diff options
author | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-24 02:27:47 -0500 |
---|---|---|
committer | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-26 11:43:54 -0500 |
commit | 621d9e5c413e561293d7484b93882d985b3fe15f (patch) | |
tree | 638f3d75761c121d9a8fb50b52a12a6686c5ac5c /base/common/src/com/netscape/cms/servlet | |
parent | 40d3643b8d91886bf210aa27f711731c81a11e49 (diff) | |
download | pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.gz pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.xz pki-621d9e5c413e561293d7484b93882d985b3fe15f.zip |
Removed unnecessary pki folder.
Previously the source code was located inside a pki folder.
This folder was created during svn migration and is no longer
needed. This folder has now been removed and the contents have
been moved up one level.
Ticket #131
Diffstat (limited to 'base/common/src/com/netscape/cms/servlet')
226 files changed, 95450 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java new file mode 100644 index 000000000..12575675c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java @@ -0,0 +1,905 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.acls.ACL; +import com.netscape.certsrv.acls.ACLEntry; +import com.netscape.certsrv.acls.IACL; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authorization.IAuthzManager; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.evaluators.IAccessEvaluator; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.usrgrp.IUGSubsystem; + +/** + * Manage Access Control List configuration + * + * @version $Revision$, $Date$ + */ +public class ACLAdminServlet extends AdminServlet { + + /** + * + */ + private static final long serialVersionUID = -322237202045924779L; + private IUGSubsystem mUG = null; + private static final String PROP_ACLS = "acls"; + private static final String PROP_EVAL = "accessEvaluator"; + private final static String INFO = "ACLAdminServlet"; + private IAuthzManager mAuthzMgr = null; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_ACL = + "LOGGING_SIGNED_AUDIT_CONFIG_ACL_3"; + + /** + * Constructs servlet. + */ + public ACLAdminServlet() { + super(); + mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + } + + /** + * initialize the servlet. + * <ul> + * <li>http.param OP_TYPE = OP_SEARCH, + * <li>http.param OP_SCOPE - the scope of the request operation: + * <ul> + * <LI>"impl" ACL implementations + * <LI>"acls" ACL rules + * <LI>"evaluatorTypes" ACL evaluators. + * </ul> + * </ul> + * + * @param config servlet configuration, read from the web.xml file + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mAuthzMgr = mAuthz.get(mAclMethod); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * + * @param req the object holding the request information + * @param resp the object holding the response information + */ + + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + + String scope = super.getParameter(req, Constants.OP_SCOPE); + String op = super.getParameter(req, Constants.OP_TYPE); + + if (op == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PROTOCOL")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + return; + } + + try { + super.authenticate(req); + } catch (IOException e) { + log(ILogger.LL_SECURITY, CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS")); + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"), + null, resp); + return; + } + + try { + AUTHZ_RES_NAME = "certServer.acl.configuration"; + + if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_ACL)) { + listResources(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_ACL_IMPLS)) { + listACLsEvaluators(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_EVALUATOR_TYPES)) { + listACLsEvaluatorTypes(req, resp); + return; + } + } else if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_ACL)) { + getResourceACL(req, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_ACL)) { + updateResources(req, resp); + return; + } + } else if (op.equals(OpDef.OP_ADD)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_ACL_IMPLS)) { + addACLsEvaluator(req, resp, scope); + return; + } + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_ACL_IMPLS)) { + deleteACLsEvaluator(req, resp, scope); + return; + } + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_OP_SCOPE")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, e.toString()); + sendResponse(ERROR, e.toString(getLocale(req)), + null, resp); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + log(ILogger.LL_DEBUG, "SRVLT_FAIL_PERFORM 2"); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"), + null, resp); + return; + } + + log(ILogger.LL_DEBUG, "SRVLT_FAIL_PERFORM 3"); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"), + null, resp); + return; + } + + /** + * list acls resources by name + */ + private void listResources(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException, + EBaseException { + + NameValuePairs params = new NameValuePairs(); + + Enumeration<ACL> res = mAuthzMgr.getACLs(); + + while (res.hasMoreElements()) { + ACL acl = (ACL) res.nextElement(); + String desc = acl.getDescription(); + + if (desc == null) + params.put(acl.getName(), ""); + else + params.put(acl.getName(), desc); + } + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * get acls information for a resource + */ + private void getResourceACL(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException, + EBaseException { + + NameValuePairs params = new NameValuePairs(); + //get resource id first + String resourceId = super.getParameter(req, Constants.RS_ID); + + if (resourceId == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + IACL acl = mAuthzMgr.getACL(resourceId); + + if (acl != null) { + Enumeration<String> rightsEnum = acl.rights(); + + StringBuffer rights = new StringBuffer(); + + if (rightsEnum.hasMoreElements()) { + while (rightsEnum.hasMoreElements()) { + if (rights.length() != 0) { + rights.append(","); + } + String right = rightsEnum.nextElement(); + + rights.append(right); + } + } + + params.put(Constants.PR_ACL_OPS, rights.toString()); + + Enumeration<ACLEntry> aclEntryEnum; + aclEntryEnum = acl.entries(); + String acis = ""; + + if (aclEntryEnum.hasMoreElements()) { + while (aclEntryEnum.hasMoreElements()) { + if (acis != "") { + acis += ";"; + } + ACLEntry aclEntry = (ACLEntry) aclEntryEnum.nextElement(); + String aci = aclEntry.getACLEntryString(); + + acis += aci; + } + } + + params.put(Constants.PR_ACI, acis); + + sendResponse(SUCCESS, null, params, resp); + return; + + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ACLS_SRVLT_RESOURCE_NOT_FOUND")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_RESOURCE_NOT_FOUND"), + null, resp); + return; + } + } + + /** + * modify acls information for a resource + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ACL used when configuring Access Control List (ACL) information + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void updateResources(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException, + EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // get resource id first + String resourceId = super.getParameter(req, Constants.RS_ID); + + if (resourceId == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // get resource acls + String resourceACLs = super.getParameter(req, Constants.PR_ACI); + String rights = super.getParameter(req, Constants.PR_ACL_RIGHTS); + String desc = super.getParameter(req, Constants.PR_ACL_DESC); + + try { + mAuthzMgr.updateACLs(resourceId, rights, resourceACLs, desc); + + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_UPDATE_FAIL"), + null, resp); + return; + } + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ACL, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ACL, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * list access evaluators by types and class paths + */ + private void listACLsEvaluators(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException, + EBaseException { + NameValuePairs params = new NameValuePairs(); + Enumeration<IAccessEvaluator> res = mAuthzMgr.aclEvaluatorElements(); + + while (res.hasMoreElements()) { + IAccessEvaluator evaluator = res.nextElement(); + + // params.add(evaluator.getType(), evaluator.getDescription()); + params.put(evaluator.getType(), evaluator.getClass().getName()); + } + + sendResponse(SUCCESS, null, params, resp); + } + + private void listACLsEvaluatorTypes(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException, + EBaseException { + NameValuePairs params = new NameValuePairs(); + Enumeration<IAccessEvaluator> res = mAuthzMgr.aclEvaluatorElements(); + + while (res.hasMoreElements()) { + IAccessEvaluator evaluator = res.nextElement(); + String[] operators = evaluator.getSupportedOperators(); + StringBuffer str = new StringBuffer(); + + for (int i = 0; i < operators.length; i++) { + if (str.length() > 0) + str.append(","); + str.append(operators[i]); + } + + params.put(evaluator.getType(), str.toString()); + } + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * add access evaluators + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ACL used when configuring Access Control List (ACL) information + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of this ACL evaluator's + * substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void addACLsEvaluator(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // get evaluator type first + String type = super.getParameter(req, Constants.RS_ID); + + if (type == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // is the evaluator type unique? + /* + if (!mACLs.isTypeUnique(type)) { + String infoMsg = "replacing existing type: "+ type; + log(ILogger.LL_WARN, infoMsg); + } + */ + + // get class + String classPath = super.getParameter(req, Constants.PR_ACL_CLASS); + + IConfigStore destStore = + mConfig.getSubStore(PROP_EVAL); + IConfigStore mStore = + destStore.getSubStore(ScopeDef.SC_ACL_IMPLS); + + // Does the class exist? + Class<?> newImpl = null; + + try { + newImpl = Class.forName(classPath); + } catch (ClassNotFoundException e) { + String errMsg = "class " + classPath + " not found"; + + log(ILogger.LL_FAILURE, errMsg); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_CLASS_LOAD_FAIL"), + null, resp); + return; + } + + // is the class an IAccessEvaluator? + try { + if (Class.forName("com.netscape.certsrv.evaluators.IAccessEvaluator").isAssignableFrom(newImpl) == false) { + String errMsg = "class not com.netscape.certsrv.evaluators.IAccessEvaluator" + + classPath; + + log(ILogger.LL_FAILURE, errMsg); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_ILL_CLASS"), + null, resp); + return; + } + } catch (Exception e) { + String errMsg = "class not com.netscape.certsrv.evaluators.IAccessEvaluator" + + classPath; + + log(ILogger.LL_FAILURE, errMsg); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_ILL_CLASS"), + null, resp); + return; + } + + IConfigStore substore = mStore.makeSubStore(type); + + substore.put(Constants.PR_ACL_CLASS, classPath); + + // commiting + try { + mConfig.commit(true); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ACLS_SRVLT_FAIL_COMMIT")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_COMMIT_FAIL"), + null, resp); + return; + } + + // Instantiate an object for this implementation + IAccessEvaluator evaluator = null; + + try { + evaluator = (IAccessEvaluator) Class.forName(classPath).newInstance(); + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_INST_CLASS_FAIL"), + null, resp); + return; + } + + // initialize the access evaluator + if (evaluator != null) { + evaluator.init(); + // add evaluator to list + mAuthzMgr.registerEvaluator(type, evaluator); + } + + //... + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ACL, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ACL, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * remove access evaluators + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ACL used when configuring Access Control List (ACL) information + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of this ACL evaluator's + * substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void deleteACLsEvaluator(HttpServletRequest req, + HttpServletResponse resp, String scope) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does the evaluator exist? + Hashtable<String, IAccessEvaluator> mEvaluators = mAuthzMgr.getAccessEvaluators(); + + if (mEvaluators.containsKey(id) == false) { + log(ILogger.LL_FAILURE, "evaluator attempted to be removed not found"); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_EVAL_NOT_FOUND"), + null, resp); + return; + } + + // it's possibl that it's being used...we have to assume that + // the administrator knows what she is doing, for now + mEvaluators.remove((Object) id); + + try { + IConfigStore destStore = + mConfig.getSubStore(PROP_EVAL); + IConfigStore mStore = + destStore.getSubStore(ScopeDef.SC_ACL_IMPLS); + + mStore.removeSubStore(id); + } catch (Exception eeee) { + //CMS.debugStackTrace(eeee); + } + // commiting + try { + mConfig.commit(true); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ACLS_SRVLT_FAIL_COMMIT")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ACL_COMMIT_FAIL"), + null, resp); + return; + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ACL, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ACL, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ACL, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Searchs for certificate requests. + */ + + /* + private void getACLs(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException, + EBaseException { + NameValuePairs params = new NameValuePairs(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(bos); + String names = getParameter(req, Constants.PT_NAMES); + StringTokenizer st = new StringTokenizer(names, ","); + while (st.hasMoreTokens()) { + String target = st.nextToken(); + ACL acl = AccessManager.getInstance().getACL(target); + oos.writeObject(acl); + } + // BASE64Encoder encoder = new BASE64Encoder(); + // params.add(Constants.PT_ACLS, encoder.encodeBuffer(bos.toByteArray())); + params.add(Constants.PT_ACLS, CMS.BtoA(bos.toByteArray())); + sendResponse(SUCCESS, null, params, resp); + } + */ + + private void log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ACLS, + level, "ACLAdminServlet: " + msg); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/AdminResources.java b/base/common/src/com/netscape/cms/servlet/admin/AdminResources.java new file mode 100644 index 000000000..a36c859d9 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/AdminResources.java @@ -0,0 +1,42 @@ +// --- 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.admin; + +import java.util.ListResourceBundle; + +/** + * A class represents a resource bundle for the remote admin. + * + * @version $Revision$, $Date$ + * @see java.util.ListResourceBundle + */ +public class AdminResources extends ListResourceBundle { + + /** + * Returns the content of this resource. + */ + public Object[][] getContents() { + return contents; + } + + /** + * Constants. The suffix represents the number of + * possible parameters. + */ + static final Object[][] contents = {}; +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/AdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/AdminServlet.java new file mode 100644 index 000000000..ce4c966ad --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/AdminServlet.java @@ -0,0 +1,1296 @@ +// --- 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.admin; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthCredentials; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.usrgrp.EUsrGrpException; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cmsutil.util.Utils; + +/** + * A class represents an administration servlet that + * is responsible to serve administrative + * operation such as configuration parameter updates. + * + * Since each administration servlet needs to perform + * authentication information parsing and response + * formulation, it makes sense to encapsulate the + * commonalities into this class. + * + * By extending this serlvet, the subclass does not + * need to re-implement the request parsing code + * (i.e. authentication information parsing). + * + * If a subsystem needs to expose configuration + * parameters management, it should create an + * administration servlet (i.e. CAAdminServlet) + * and register it to RemoteAdmin subsystem. + * + * <code> + * public class CAAdminServlet extends AdminServlet { + * ... + * } + * </code> + * + * @version $Revision$, $Date$ + */ +public class AdminServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = 7740464244137421542L; + private final static String HDR_AUTHORIZATION = "Authorization"; + private final static String HDR_LANG = "accept-language"; + private final static String HDR_CONTENT_LEN = "Content-Length"; + + protected ILogger mLogger = CMS.getLogger(); + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + private IUGSubsystem mUG = null; + protected IConfigStore mConfig = null; + protected IAuthzSubsystem mAuthz = null; + + // we don't allow to switch authz db mid-way, for now + protected String mAclMethod = null; + protected String mOp = ""; + protected static String AUTHZ_RES_NAME = "certServer"; + protected AuthzToken mToken; + + private String mServletID = null; + 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"; + public final static String PROP_ID = "ID"; + public final static String AUTHZ_CONFIG_STORE = "authz"; + public final static String AUTHZ_SRC_TYPE = "sourceType"; + public final static String AUTHZ_SRC_LDAP = "ldap"; + public final static String AUTHZ_SRC_XML = "web.xml"; + public static final String CERT_ATTR = + "javax.servlet.request.X509Certificate"; + + public final static String SIGNED_AUDIT_SCOPE = "Scope"; + public final static String SIGNED_AUDIT_OPERATION = "Operation"; + public final static String SIGNED_AUDIT_RESOURCE = "Resource"; + public final static String SIGNED_AUDIT_RULENAME = "RULENAME"; + public final static String SIGNED_AUDIT_PASSWORD_VALUE = "********"; + public final static String SIGNED_AUDIT_EMPTY_NAME_VALUE_PAIR = "Unknown"; + public final static String SIGNED_AUDIT_NAME_VALUE_DELIMITER = ";;"; + public final static String SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER = "+"; + + private final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL = + "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4"; + private final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3"; + private final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL = + "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4"; + private final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4"; + private final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME = + "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3"; + private final static String CERTUSERDB = + IAuthSubsystem.CERTUSERDB_AUTHMGR_ID; + private final static String PASSWDUSERDB = + IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID; + + /** + * Constructs generic administration servlet. + */ + public AdminServlet() { + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + mConfig = CMS.getConfigStore(); + + String srcType = AUTHZ_SRC_LDAP; + + try { + IConfigStore authzConfig = mConfig.getSubStore(AUTHZ_CONFIG_STORE); + + srcType = authzConfig.getString(AUTHZ_SRC_TYPE, AUTHZ_SRC_LDAP); + } catch (EBaseException e) { + CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_FAIL_SRC_TYPE")); + } + mAuthz = + (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + + mServletID = getSCparam(sc, PROP_ID, "servlet id unknown"); + CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", mServletID)); + + if (srcType.equalsIgnoreCase(AUTHZ_SRC_XML)) { + CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", "")); + // get authz mgr from xml file; if not specified, use + // ldap by default + mAclMethod = getSCparam(sc, PROP_AUTHZ_MGR, AUTHZ_MGR_LDAP); + + if (mAclMethod.equalsIgnoreCase(AUTHZ_MGR_BASIC)) { + String aclInfo = sc.getInitParameter(PROP_ACL); + + if (aclInfo != null) { + try { + addACLInfo(aclInfo); + //mAuthz.authzMgrAccessInit(mAclMethod, aclInfo); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_FAIL")); + throw new ServletException("failed to init authz info from xml config file"); + } + CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_DONE", mServletID)); + } else { // PROP_AUTHZ_MGR not specified, use default authzmgr + CMS.debug("AdminServlet: " + + CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_ACL, mServletID, AUTHZ_MGR_LDAP)); + } + } else { // PROP_AUTHZ_MGR not specified, use default authzmgr + CMS.debug("AdminServlet: " + + CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_AUTHZ_MGR, mServletID, AUTHZ_MGR_LDAP)); + } + + } else { + mAclMethod = AUTHZ_MGR_LDAP; + CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTH_LDAP_NOT_XML", mServletID)); + } + } + + public void outputHttpParameters(HttpServletRequest httpReq) { + CMS.debug("AdminServlet:service() uri = " + httpReq.getRequestURI()); + @SuppressWarnings("unchecked") + Enumeration<String> paramNames = httpReq.getParameterNames(); + while (paramNames.hasMoreElements()) { + String pn = 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 (pn.startsWith("__") || + pn.endsWith("password") || + pn.endsWith("passwd") || + pn.endsWith("pwd") || + pn.equalsIgnoreCase("admin_password_again") || + pn.equalsIgnoreCase("directoryManagerPwd") || + pn.equalsIgnoreCase("bindpassword") || + pn.equalsIgnoreCase("bindpwd") || + pn.equalsIgnoreCase("passwd") || + pn.equalsIgnoreCase("password") || + pn.equalsIgnoreCase("pin") || + pn.equalsIgnoreCase("pwd") || + pn.equalsIgnoreCase("pwdagain") || + pn.equalsIgnoreCase("uPasswd")) { + CMS.debug("AdminServlet::service() param name='" + pn + + "' value='(sensitive)'"); + } else { + CMS.debug("AdminServlet::service() param name='" + pn + + "' value='" + httpReq.getParameter(pn) + "'"); + } + } + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + boolean running_state = CMS.isInRunningState(); + + if (!running_state) + throw new IOException( + "CMS server is not ready to serve."); + + if (CMS.debugOn()) { + outputHttpParameters(req); + } + } + + private void addACLInfo(String info) throws EBaseException { + StringTokenizer tokenizer = new StringTokenizer(info, "#"); + + while (tokenizer.hasMoreTokens()) { + String acl = (String) tokenizer.nextToken(); + + mAuthz.authzMgrAccessInit(mAclMethod, acl); + } + } + + private String getSCparam(ServletConfig sc, String param, String defVal) { + String val = sc.getInitParameter(param); + + if (val == null) + return defVal; + else + return val; + } + + /** + * Authenticates to the identity scope with the given + * userid and password via identity manager. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_FAIL used when authentication fails (in case of SSL-client auth, only + * webserver env can pick up the SSL violation; CMS authMgr can pick up cert mis-match, so this event is used) + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_SUCCESS used when authentication succeeded + * </ul> + * + * @exception IOException an input/output error has occurred + */ + protected void authenticate(HttpServletRequest req) throws + IOException { + + String auditMessage = null; + String auditUID = ILogger.UNIDENTIFIED; + String authType = ""; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + try { + IConfigStore configStore = CMS.getConfigStore(); + + authType = configStore.getString("authType"); + } catch (EBaseException e) { + // do nothing for now. + } + IAuthSubsystem auth = (IAuthSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + X509Certificate cert = null; + + if (authType.equals("sslclientauth")) { + X509Certificate[] allCerts = + (X509Certificate[]) req.getAttribute(CERT_ATTR); + + if (allCerts == null || allCerts.length == 0) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + CERTUSERDB, + auditUID); + + audit(auditMessage); + + throw new IOException("No certificate"); + } + + cert = allCerts[0]; + try { + byte[] certEncoded = cert.getEncoded(); + + cert = new X509CertImpl(certEncoded); + + // save the "Subject DN" of this certificate in case it + // must be audited as an authentication failure + String certUID = cert.getSubjectDN().getName(); + + if (certUID != null) { + certUID = certUID.trim(); + + if (!(certUID.equals(""))) { + auditUID = certUID; + } + } + } catch (Exception e) { + } + } + + // create session (if we don't, identity will reject + // the authentication). + SessionContext sc = SessionContext.getContext(); + IAuthToken token = null; + + log(ILogger.LL_DEBUG, CMS.getLogMessage("ADMIN_SRVLT_ABOUT_AUTH", + mServletID)); + try { + if (authType.equals("sslclientauth")) { + IAuthManager authMgr = auth.get(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID); + IAuthCredentials authCreds = + getAuthCreds(authMgr, cert); + + token = (AuthToken) authMgr.authenticate(authCreds); + } else { + String authToken = req.getHeader(HDR_AUTHORIZATION); + String b64s = authToken.substring( + authToken.lastIndexOf(' ') + 1); + String authCode = new String(Utils.base64decode(b64s)); + String userid = authCode.substring(0, + authCode.indexOf(':')); + String password = authCode.substring( + authCode.indexOf(':') + 1); + AuthCredentials cred = new AuthCredentials(); + + // save the "userid" of this certificate in case it + // must be audited as an authentication failure + String pwdUID = userid; + + if (pwdUID != null) { + pwdUID = pwdUID.trim(); + + if (!(pwdUID.equals(""))) { + auditUID = pwdUID; + } + } + + cred.set("uid", userid); + cred.set("pwd", password); + + token = auth.authenticate(cred, + IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID); + CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FOR_SRVLT", + mServletID)); + } + } catch (EBaseException e) { + //will fix it later for authorization + /* + String errMsg = "authenticate(): " + + AdminResources.SRVLT_FAIL_AUTHS +": "+userid +":"+ + e.getMessage(); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAIL", + CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS"), + userid,e.getMessage())); + */ + + if (authType.equals("sslclientauth")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + CERTUSERDB, + auditUID); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + PASSWDUSERDB, + auditUID); + + audit(auditMessage); + } + + throw new IOException("authentication failed"); + } + + try { + String tuserid = token.getInString("userid"); + + if (tuserid == null) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_NO_AUTH_TOKEN", + tuserid)); + + if (authType.equals("sslclientauth")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + CERTUSERDB, + auditUID); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + PASSWDUSERDB, + auditUID); + + audit(auditMessage); + } + + throw new IOException("authentication failed"); + } + + // get user. + // this either returns null or + // throws exception when user not found + IUser user = mUG.getUser(tuserid); + + if (user == null) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_FOUND", + tuserid)); + + if (authType.equals("sslclientauth")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + CERTUSERDB, + auditUID); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + PASSWDUSERDB, + auditUID); + + audit(auditMessage); + } + + throw new IOException("authentication failed"); + } + + // set session context to work with some agent servlets. + // XXX should see if this can be used for more things. + SessionContext sessionContext = SessionContext.getContext(); + + sessionContext.put(SessionContext.AUTH_TOKEN, token); + sessionContext.put(SessionContext.USER_ID, tuserid); + sessionContext.put(SessionContext.USER, user); + } catch (EUsrGrpException e) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_USR_GRP_ERR", e.toString())); + + if (authType.equals("sslclientauth")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + CERTUSERDB, + auditUID); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + PASSWDUSERDB, + auditUID); + + audit(auditMessage); + } + + throw new IOException("authentication failed"); + } + + // build locale based on the client language + Locale locale = getLocale(req); + + sc.put(SessionContext.LOCALE, locale); + + if (authType.equals("sslclientauth")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + auditSubjectID(), + ILogger.SUCCESS, + CERTUSERDB); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + auditSubjectID(), + ILogger.SUCCESS, + PASSWDUSERDB); + + audit(auditMessage); + } + } catch (IOException eAudit1) { + if (authType.equals("sslclientauth")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + CERTUSERDB, + auditUID); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + ILogger.UNIDENTIFIED, + ILogger.FAILURE, + PASSWDUSERDB, + auditUID); + + audit(auditMessage); + } + + // rethrow the specific exception to be handled later + throw eAudit1; + } + } + + public static AuthCredentials getAuthCreds( + IAuthManager authMgr, X509Certificate clientCert) + throws EBaseException { + // get credentials from http parameters. + String[] reqCreds = authMgr.getRequiredCreds(); + AuthCredentials creds = new AuthCredentials(); + + for (int i = 0; i < reqCreds.length; i++) { + String reqCred = reqCreds[i]; + + if (reqCred.equals(IAuthManager.CRED_SSL_CLIENT_CERT)) { + // cert could be null; + creds.set(reqCred, new X509Certificate[] { clientCert } + ); + } + } + return creds; + } + + /** + * Authorize must occur after Authenticate + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful + * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CMS that's when one + * accesses a role port) + * </ul> + * + * @param req HTTP servlet request + * @return the authorization token + */ + protected AuthzToken authorize(HttpServletRequest req) { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditACLResource = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditOperation = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String resource = null; + String operation = null; + + // use session context to get auth token for now + SessionContext sc = SessionContext.getContext(); + IAuthToken authToken = (IAuthToken) sc.get(SessionContext.AUTH_TOKEN); + + AuthzToken authzTok = null; + + CMS.debug("AdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CHECK_AUTHZ_AUTH", mServletID)); + // hardcoded for now .. just testing + try { + // we check both "read" and "write" for now. later within + // each servlet, they can break it down + authzTok = mAuthz.authorize(mAclMethod, authToken, AUTHZ_RES_NAME, mOp); + // initialize the ACL resource, overwriting "auditACLResource" + // if it is not null + resource = (String) + authzTok.get(AuthzToken.TOKEN_AUTHZ_RESOURCE); + if (resource != null) { + auditACLResource = resource.trim(); + } + + // initialize the operation, overwriting "auditOperation" + // if it is not null + operation = (String) + authzTok.get(AuthzToken.TOKEN_AUTHZ_OPERATION); + if (operation != null) { + auditOperation = operation.trim(); + } + + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTH_SUCCEED", mServletID)); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return null; + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return null; + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return null; + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.SUCCESS, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return authzTok; + } + + /** + * 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; + } + + public static int SUCCESS = 0; + public static int ERROR = 1; + public static int RESTART = -1; + + /** + * Sends response. + * + * @param returnCode return code + * @param errorMsg localized error message + * @param params result parameters + * @param resp HTTP servlet response + */ + protected void sendResponse(int returnCode, String errorMsg, + NameValuePairs params, HttpServletResponse resp) + throws IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + + dos.writeInt(returnCode); + if (errorMsg != null) { + dos.writeUTF(errorMsg); + } + StringBuffer buf = new StringBuffer(); + + if (params != null) { + Collection<String> names = params.keySet(); + + if (!names.isEmpty()) { + for (Iterator<String> i = names.iterator(); i.hasNext(); ) { + String name = i.next(); + String value = java.net.URLEncoder.encode( + params.get(name), "UTF-8"); + + buf.append(java.net.URLEncoder.encode(name, "UTF-8") + + "=" + value); + if (i.hasNext()) + buf.append("&"); + } + byte content[] = buf.toString().getBytes(); + + dos.write(content, 0, content.length); + } + } + byte msg[] = bos.toByteArray(); + + resp.setContentLength(msg.length); + resp.getOutputStream().write(msg); + resp.getOutputStream().flush(); + } + + /** + * URL decodes the given string. + */ + protected String URLdecode(String s) { + if (s == null) + return null; + ByteArrayOutputStream out = new ByteArrayOutputStream(s.length()); + + for (int i = 0; i < s.length(); i++) { + int c = (int) s.charAt(i); + + if (c == '+') { + out.write(' '); + } else if (c == '%') { + int c1 = Character.digit(s.charAt(++i), 16); + int c2 = Character.digit(s.charAt(++i), 16); + + out.write((char) (c1 * 16 + c2)); + } else { + out.write(c); + } + } // end for + return out.toString(); + } + + protected String getParameter(HttpServletRequest req, String name) { + // Servlet framework already apply URLdecode + // return URLdecode(req.getParameter(name)); + return req.getParameter(name); + } + + /** + * Generic configuration store get operation. + */ + protected synchronized void getConfig( + IConfigStore config, HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + //if (name.equals(Constants.PT_OP)) + // continue; + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + + //System.out.println(name); + //System.out.println(name+","+config.getString(name)); + params.put(name, config.getString(name)); + } + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Generic configuration store set operation. + * The caller is responsible to do validiation before + * calling this, and commit changes after this call. + */ + protected synchronized void setConfig( + IConfigStore config, HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + //if (name.equals(Constants.PT_OP)) + // continue; + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + // XXX Need validation... + // XXX what if update failed + config.putString(name, req.getParameter(name)); + } + commit(true); + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Lists configuration store. + */ + protected synchronized void listConfig( + IConfigStore config, HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + Enumeration<String> e = config.getPropertyNames(); + NameValuePairs params = new NameValuePairs(); + + while (e.hasMoreElements()) { + String s = e.nextElement(); + + params.put(s, config.getString(s)); + } + sendResponse(SUCCESS, null, params, resp); + } + + /** + * authorize a user based on its authentication credentials. + */ + public boolean authorize(IAuthToken token) throws EBaseException { + String mGroupNames[] = { "Administrators" }; + boolean mAnd = true; + + try { + String userid = token.getInString("userid"); + + if (userid == null) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_GRP_AUTHZ_FAIL", userid)); + return false; + } + + // get user. + // this either returns null or throws exception when user not found + IUser user = mUG.getUser(userid); + + if (user == null) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_IN_DB", userid)); + return false; + } + + // set session context to work with some agent servlets. + // XXX should see if this can be used for more things. + SessionContext sessionContext = SessionContext.getContext(); + + sessionContext.put(SessionContext.AUTH_TOKEN, token); + sessionContext.put(SessionContext.USER_ID, userid); + sessionContext.put(SessionContext.USER, user); + + // check group membership of user. + if (mAnd) { + for (int i = 0; i < mGroupNames.length; i++) { + if (!mUG.isMemberOf(user, mGroupNames[i])) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_IN_GRP", userid, + mGroupNames[i])); + return false; + } + } + return true; + } else { + for (int i = 0; i < mGroupNames.length; i++) { + if (mUG.isMemberOf(user, mGroupNames[i])) { + mLogger.log(ILogger.EV_SYSTEM, + ILogger.S_OTHER, ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_GRP_AUTH_SUCC_USER", userid, + mGroupNames[i])); + return true; + } + } + StringBuffer groups = new StringBuffer(); + groups.append(mGroupNames[0]); + + for (int j = 1; j < mGroupNames.length; j++) { + groups.append(","); + groups.append(mGroupNames[j]); + } + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_USER_NOT_ANY_GRP", userid, groups.toString())); + return false; + } + } catch (EUsrGrpException e) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_USR_GRP_ERR", e.toString())); + return false; + } + } + + /** + * FileConfigStore functionality + * + * The original config file is moved to <filename>.<date>. + * Commits the current properties to the configuration file. + * <P> + * + * @param createBackup true if a backup file should be created + */ + protected void commit(boolean createBackup) throws EBaseException { + mConfig.commit(createBackup); + } + + private void log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_ADMIN, + level, "AdminServlet: " + msg); + } + + /** + * Signed Audit Log + * + * This method is inherited by all extended admin servlets + * and is called to store messages to the signed audit log. + * <P> + * + * @param msg signed audit log message + */ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (mSignedAuditLogger == null) { + return; + } + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Subject ID + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to obtain the "SubjectID" for + * a signed audit log message. + * <P> + * + * @return id string containing the signed audit log message SubjectID + */ + protected String auditSubjectID() { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String subjectID = null; + + // Initialize subjectID + SessionContext auditContext = SessionContext.getExistingContext(); + + if (auditContext != null) { + subjectID = (String) + auditContext.get(SessionContext.USER_ID); + + if (subjectID != null) { + subjectID = subjectID.trim(); + } else { + subjectID = ILogger.NONROLEUSER; + } + } else { + subjectID = ILogger.UNIDENTIFIED; + } + + return subjectID; + } + + /** + * Signed Audit Parameters + * + * This method is inherited by all extended admin servlets and + * is called to extract parameters from the HttpServletRequest + * and return a string of name;;value pairs separated by a '+' + * if more than one name;;value pair exists. + * <P> + * + * @param req HTTP servlet request + * @return a delimited string of one or more delimited name/value pairs + */ + protected String auditParams(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String parameters = SIGNED_AUDIT_EMPTY_NAME_VALUE_PAIR; + String value = null; + + // always identify the scope of the request + if (req.getParameter(Constants.OP_SCOPE) != null) { + parameters = SIGNED_AUDIT_SCOPE + + SIGNED_AUDIT_NAME_VALUE_DELIMITER + + req.getParameter(Constants.OP_SCOPE); + } + + // identify the operation type of the request + if (req.getParameter(Constants.OP_TYPE) != null) { + parameters += SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER; + + parameters += SIGNED_AUDIT_OPERATION + + SIGNED_AUDIT_NAME_VALUE_DELIMITER + + req.getParameter(Constants.OP_TYPE); + } + + // identify the resource type of the request + if (req.getParameter(Constants.RS_ID) != null) { + parameters += SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER; + + parameters += SIGNED_AUDIT_RESOURCE + + SIGNED_AUDIT_NAME_VALUE_DELIMITER + + req.getParameter(Constants.RS_ID); + } + + // identify any remaining request parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + // skip previously extracted parameters + if (name.equals(Constants.OP_SCOPE)) { + continue; + } + if (name.equals(Constants.OP_TYPE)) { + continue; + } + if (name.equals(Constants.RS_ID)) { + continue; + } + + // skip "RULENAME" parameter + if (name.equals(SIGNED_AUDIT_RULENAME)) { + continue; + } + + parameters += SIGNED_AUDIT_NAME_VALUE_PAIRS_DELIMITER; + + value = req.getParameter(name); + if (value != null) { + value = value.trim(); + + if (value.equals("")) { + parameters += name + + SIGNED_AUDIT_NAME_VALUE_DELIMITER + + ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + // + // To fix Blackflag Bug # 613800: + // + // Check "com.netscape.certsrv.common.Constants" for + // case-insensitive "password", "pwd", and "passwd" + // name fields, and hide any password values: + // + /* "password" */if (name.equals(Constants.PASSWORDTYPE) || + name.equals(Constants.TYPE_PASSWORD) || + name.equals(Constants.PR_USER_PASSWORD) || + name.equals(Constants.PT_OLD_PASSWORD) || + name.equals(Constants.PT_NEW_PASSWORD) || + name.equals(Constants.PT_DIST_STORE) || + name.equals(Constants.PT_DIST_EMAIL) || + /* "pwd" */name.equals(Constants.PR_AUTH_ADMIN_PWD) || + // ignore this one name.equals( Constants.PR_BINDPWD_PROMPT ) || + name.equals(Constants.PR_DIRECTORY_MANAGER_PWD) || + name.equals(Constants.PR_OLD_AGENT_PWD) || + name.equals(Constants.PR_AGENT_PWD) || + name.equals(Constants.PT_PUBLISH_PWD) || + /* "passwd" */name.equals(Constants.PR_BIND_PASSWD) || + name.equals(Constants.PR_BIND_PASSWD_AGAIN) || + name.equals(Constants.PR_TOKEN_PASSWD)) { + + // hide password value + parameters += name + + SIGNED_AUDIT_NAME_VALUE_DELIMITER + + SIGNED_AUDIT_PASSWORD_VALUE; + } else { + // process normally + parameters += name + + SIGNED_AUDIT_NAME_VALUE_DELIMITER + + value; + } + } + } else { + parameters += name + + SIGNED_AUDIT_NAME_VALUE_DELIMITER + + ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + return parameters; + } + + /** + * Signed Audit Groups + * + * This method is called to extract all "groups" associated + * with the "auditSubjectID()". + * <P> + * + * @param SubjectID string containing the signed audit log message SubjectID + * @return a delimited string of groups associated + * with the "auditSubjectID()" + */ + private String auditGroups(String SubjectID) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + if ((SubjectID == null) || + (SubjectID.equals(ILogger.UNIDENTIFIED))) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + Enumeration<IGroup> groups = null; + + try { + groups = mUG.findGroups("*"); + } catch (Exception e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + StringBuffer membersString = new StringBuffer(); + + while (groups.hasMoreElements()) { + IGroup group = groups.nextElement(); + + if (group.isMember(SubjectID) == true) { + if (membersString.length() != 0) { + membersString.append(", "); + } + + membersString.append(group.getGroupID()); + } + } + + if (membersString.length() != 0) { + return membersString.toString(); + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + protected NameValuePairs convertStringArrayToNVPairs(String[] s) { + if (s == null) + return null; + NameValuePairs nvps = new NameValuePairs(); + int i; + + for (i = 0; i < s.length; i++) { + int j = s[i].indexOf(";"); + String paramName = s[i].substring(0, j); + String args = s[i].substring(j + 1); + + nvps.put(paramName, args); + } + return nvps; + + } + + protected static IExtendedPluginInfo getClassByNameAsExtendedPluginInfo(String className) { + + IExtendedPluginInfo epi = null; + + try { + // here is the new dummy obj created + Object o = Class.forName(className).newInstance(); + + epi = (IExtendedPluginInfo) o; + } catch (Exception e) { + } + + return epi; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java new file mode 100644 index 000000000..cacd0b5d0 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java @@ -0,0 +1,1721 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthManagerProxy; +import com.netscape.certsrv.authentication.AuthMgrPlugin; +import com.netscape.certsrv.authentication.EAuthException; +import com.netscape.certsrv.authentication.EAuthMgrNotFound; +import com.netscape.certsrv.authentication.EAuthMgrPluginNotFound; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.DestDef; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.ldap.ILdapAuthInfo; +import com.netscape.certsrv.logging.ILogger; + +/** + * A class representing an administration servlet for the + * Authentication Management subsystem. This servlet is responsible + * to serve configuration requests for the Auths Management subsystem. + * + * + * @version $Revision$, $Date$ + */ +public class AuthAdminServlet extends AdminServlet { + + /** + * + */ + private static final long serialVersionUID = -6258411211380144425L; + private final static String INFO = "AuthAdminServlet"; + private IAuthSubsystem mAuths = null; + + private final static String PW_PASSWORD_CACHE_ADD = + "PASSWORD_CACHE_ADD"; + private final static String VIEW = ";" + Constants.VIEW; + private final static String EDIT = ";" + Constants.EDIT; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_AUTH = + "LOGGING_SIGNED_AUDIT_CONFIG_AUTH_3"; + + public AuthAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mAuths = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + AUTHZ_RES_NAME = "certServer.auth.configuration"; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * retrieve extended plugin info such as brief description, type info + * from policy, authentication, + * need to add: listener, mapper and publishing plugins + * --- same as policy, should we move this into extendedpluginhelper? + */ + private void getExtendedPluginInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + int colon = id.indexOf(':'); + + String implType = id.substring(0, colon); + String implName = id.substring(colon + 1); + + NameValuePairs params = + getExtendedPluginInfo(getLocale(req), implType, implName); + + sendResponse(SUCCESS, null, params, resp); + } + + private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) { + IExtendedPluginInfo ext_info = null; + Object impl = null; + + impl = mAuths.getAuthManagerPlugin(implName); + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + } + + return nvps; + + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + if (op == null) { + //System.out.println("SRVLT_INVALID_PROTOCOL"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + return; + } + + // if it is not authentication, that means it is for CSC admin ping. + // the best way to do is to define another protocol for ping and move + // it to the generic servlet which is admin servlet. + if (!op.equals(OpDef.OP_AUTH)) { + if (scope.equals(ScopeDef.SC_AUTH)) { + String id = req.getParameter(Constants.RS_ID); + + // for CSC admin ping only + if (op.equals(OpDef.OP_READ) && + id.equals(Constants.RS_ID_CONFIG)) { + + // no need to authenticate this. if we're alive, return true. + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_PING, Constants.TRUE); + sendResponse(SUCCESS, null, params, resp); + return; + } else { + //System.out.println("SRVLT_INVALID_OP_TYPE"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op), + null, resp); + return; + } + } + } + + try { + if (op.equals(OpDef.OP_AUTH)) { + if (scope.equals(ScopeDef.SC_AUTHTYPE)) { + IConfigStore configStore = CMS.getConfigStore(); + String val = configStore.getString("authType", "pwd"); + NameValuePairs params = new NameValuePairs(); + + params.put("authType", val); + sendResponse(SUCCESS, null, params, resp); + return; + } + } + } catch (Exception e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"), + null, resp); + return; + } + // for the rest + try { + super.authenticate(req); + if (op.equals(OpDef.OP_AUTH)) { // for admin authentication only + sendResponse(SUCCESS, null, null, resp); + return; + } + } catch (IOException e) { + //System.out.println("SRVLT_FAIL_AUTHS"); + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"), + null, resp); + return; + } + + try { + // perform operation based on scope + if (scope != null) { + AUTHZ_RES_NAME = "certServer.auth.configuration"; + if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) { + try { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + getExtendedPluginInfo(req, resp); + return; + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + } + if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) { + listAuthMgrPlugins(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) { + listAuthMgrInsts(req, resp); + return; + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) { + getConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) { + getInstConfig(req, resp); + return; + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_ADD)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) { + addAuthMgrPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) { + addAuthMgrInst(req, resp, scope); + return; + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_AUTH_IMPLS)) { + delAuthMgrPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) { + delAuthMgrInst(req, resp, scope); + return; + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_AUTH_MGR_INSTANCE)) { + modAuthMgrInst(req, resp, scope); + return; + } + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"), + null, resp); + return; + } + + private void putUserPWPair(String combo) { + int semicolon; + + semicolon = combo.indexOf(";"); + String user = combo.substring(0, semicolon); + String pw = combo.substring(semicolon + 1); + + CMS.putPasswordCache(user, pw); + } + + /** + * Add authentication manager plug-in + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of this authentication + * manager's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + + private synchronized void addAuthMgrPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + // is the manager id unique? + if (mAuths.getPlugins().containsKey((Object) id)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse( + ERROR, + new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_DUP_MGR_PLUGIN_ID", + id)).toString(), + null, resp); + return; + } + + String classPath = req.getParameter(Constants.PR_AUTH_CLASS); + + if (classPath == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_NULL_AUTHMGR_CLASSNAME"), + null, resp); + return; + } + + if (classPath.equals("com.netscape.cmscore.authentication.PasswdUserDBAuthentication") || + classPath.equals("com.netscape.cmscore.authentication.CertUserDBAuthentication")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp); + return; + } + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + // Does the class exist? + + Class<IAuthManager> newImpl = null; + + try { + @SuppressWarnings("unchecked") + Class<IAuthManager> tmpImpl = (Class<IAuthManager>) Class.forName(classPath); + newImpl = tmpImpl; + } catch (ClassNotFoundException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_PLUGIN_NOT_FOUND"), + null, resp); + return; + } catch (IllegalArgumentException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_PLUGIN_NOT_FOUND"), + null, resp); + return; + } + + // is the class an IAuthManager? + try { + if (IAuthManager.class.isAssignableFrom(newImpl) == false) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_ILL_CLASS"), + null, resp); + return; + } + } catch (NullPointerException e) { // unlikely, only if newImpl null. + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_ILL_CLASS"), + null, resp); + return; + } + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(Constants.PR_AUTH_CLASS, classPath); + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // add manager to registry. + AuthMgrPlugin plugin = new AuthMgrPlugin(id, classPath); + + mAuths.getPlugins().put(id, plugin); + mAuths.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_PLUGIN_ADD", id)); + + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Add authentication manager instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of this authentication + * manager's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void addAuthMgrInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // is the manager instance id unique? + if (mAuths.getInstances().containsKey((Object) id)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_ILL_MGR_INST_ID"), + null, resp); + return; + } + + // get required parameters + // SC_AUTH_IMPL_NAME is absolutely required, the rest depend on + // on each authenticaton manager + String implname = req.getParameter(Constants.PR_AUTH_IMPL_NAME); + + if (implname == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_MISSING_PARAMS"), + null, resp); + return; + } + + // prevent agent & admin creation. + if (implname.equals(IAuthSubsystem.PASSWDUSERDB_PLUGIN_ID) || + implname.equals(IAuthSubsystem.CERTUSERDB_PLUGIN_ID)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp); + } + + // check if implementation exists. + AuthMgrPlugin plugin = + (AuthMgrPlugin) mAuths.getPlugins().get(implname); + + if (plugin == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse( + ERROR, + new EAuthMgrPluginNotFound(CMS.getUserMessage(getLocale(req), + "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", implname)).toString(), + null, resp); + return; + } + + // now the rest of config parameters + // note that we only check to see if the required parameters + // are there, but not checking the values are valid + String[] configParams = mAuths.getConfigParams(implname); + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + IConfigStore substore = instancesConfig.makeSubStore(id); + + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + String key = configParams[i]; + String val = req.getParameter(key); + + if (val != null) { + substore.put(key, val); + } + } + } + substore.put(IAuthSubsystem.PROP_PLUGIN, implname); + + String pwadd = req.getParameter(PW_PASSWORD_CACHE_ADD); + + if (pwadd != null) { + putUserPWPair(pwadd); + } + + // Instantiate an object for this implementation + String className = plugin.getClassPath(); + IAuthManager authMgrInst = null; + + try { + authMgrInst = (IAuthManager) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // cleanup + instancesConfig.removeSubStore(id); + sendResponse( + ERROR, + new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL", + className)).toString(), + null, resp); + return; + } catch (InstantiationException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + instancesConfig.removeSubStore(id); + sendResponse( + ERROR, + new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL", + className)).toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + instancesConfig.removeSubStore(id); + sendResponse( + ERROR, + new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL", + className)).toString(), + null, resp); + return; + } + + // initialize the authentication manager + try { + authMgrInst.init(id, implname, substore); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // don't commit in this case and cleanup the new substore. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // clean up. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // inited and commited ok. now add manager instance to list. + mAuths.add(id, authMgrInst); + + mAuths.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_MGR_ADD", id)); + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_AUTH_IMPL_NAME, implname); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private synchronized void listAuthMgrPlugins(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mAuths.getPlugins().keys(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + AuthMgrPlugin value = (AuthMgrPlugin) + mAuths.getPlugins().get(name); + + if (value.isVisible()) { + params.put(name, value.getClassPath() + EDIT); + } + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void listAuthMgrInsts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + for (Enumeration<?> e = mAuths.getInstances().keys(); e.hasMoreElements();) { + String name = (String) e.nextElement(); + AuthManagerProxy proxy = (AuthManagerProxy) mAuths.getInstances().get(name); + IAuthManager value = proxy.getAuthManager(); + String enableStr = "enabled"; + + if (!proxy.isEnable()) { + enableStr = "disabled"; + } + + AuthMgrPlugin amgrplugin = (AuthMgrPlugin) + mAuths.getPlugins().get(value.getImplName()); + + if (!amgrplugin.isVisible()) { + params.put(name, value.getImplName() + ";invisible;" + enableStr); + } else { + params.put(name, value.getImplName() + ";visible;" + enableStr); + } + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * Delete authentication manager plug-in + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of this authentication + * manager's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void delAuthMgrPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // prevent deletion of admin and agent. + if (id.equals(IAuthSubsystem.PASSWDUSERDB_PLUGIN_ID) || + id.equals(IAuthSubsystem.CERTUSERDB_PLUGIN_ID)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp); + } + + // does auth manager exist? + if (mAuths.getPlugins().containsKey(id) == false) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse( + ERROR, + new EAuthMgrPluginNotFound(CMS.getUserMessage(getLocale(req), + "CMS_AUTHENTICATION_DUP_MGR_PLUGIN_ID", id)).toString(), + null, resp); + return; + } + + // first check if any instances from this auth manager + // DON'T remove auth manager if any instance + for (Enumeration<?> e = mAuths.getInstances().keys(); e.hasMoreElements();) { + IAuthManager authMgr = (IAuthManager) mAuths.get((String) e.nextElement()); + + if (authMgr.getImplName() == id) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_MGR_IN_USE"), + null, resp); + return; + } + } + + // then delete this auth manager + mAuths.getPlugins().remove((Object) id); + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } + } + + /** + * Delete authentication manager instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of this authentication + * manager's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void delAuthMgrInst(HttpServletRequest req, + HttpServletResponse resp, String scope) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // prevent deletion of admin and agent. + if (id.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID) || + id.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp); + } + + // does auth manager instance exist? + if (mAuths.getInstances().containsKey(id) == false) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse( + ERROR, + new EAuthMgrNotFound(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", + id)).toString(), + null, resp); + return; + } + + // only remove from memory + // cannot shutdown because we don't keep track of whether it's + // being used. + mAuths.getInstances().remove(id); + + // remove the configuration. + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + //This only works in the fact that we only support one instance per + //auth plugin. + ILdapAuthInfo authInfo = CMS.getLdapAuthInfo(); + + authInfo.removePassword("Rule " + id); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * used for getting the required configuration parameters (with + * possible default values) for a particular auth manager plugin + * implementation name specified in the RS_ID. Actually, there is + * no logic in here to set any default value here...there's no + * default value for any parameter in this authentication subsystem + * at this point. Later, if we do have one (or some), it can be + * added. The interface remains the same. + */ + private synchronized void getConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + + String implname = req.getParameter(Constants.RS_ID); + + if (implname == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + String[] configParams = mAuths.getConfigParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.put(Constants.PR_AUTH_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + params.put(configParams[i], ""); + } + } + sendResponse(0, null, params, resp); + return; + } + + private synchronized void getInstConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does auth manager instance exist? + if (mAuths.getInstances().containsKey(id) == false) { + sendResponse( + ERROR, + new EAuthMgrNotFound(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", id)) + .toString(), + null, resp); + return; + } + + IAuthManager mgrInst = (IAuthManager) mAuths.get(id); + IConfigStore config = mgrInst.getConfigStore(); + String[] configParams = mgrInst.getConfigParams(); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_AUTH_IMPL_NAME, mgrInst.getImplName()); + // implName is always required so always send it. + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + String key = configParams[i]; + String val = (String) config.get(key); + + if (val != null) { + params.put(key, val); + } else { + params.put(key, ""); + } + } + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * Modify authentication manager instance + * This will actually create a new instance with new configuration + * parameters and replace the old instance if the new instance is + * created and initialized successfully. + * The old instance is left running, so this is very expensive. + * Restart of server recommended. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_AUTH used when configuring authentication + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of this authentication + * manager's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void modAuthMgrInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + // expensive operation. + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // prevent modification of admin and agent. + if (id.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID) || + id.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_BASE_PERMISSION_DENIED"), null, resp); + } + + // Does the manager instance exist? + if (!mAuths.getInstances().containsKey((Object) id)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage("CMS_AUTHENTICATION_MGR_IMPL_NOT_FOUND"), + null, resp); + return; + } + + // get new implementation (same or different.) + String implname = req.getParameter(Constants.PR_AUTH_IMPL_NAME); + + if (implname == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage("CMS_AUTHENTICATION_MISSING_PARAMS"), + null, resp); + return; + } + + // get plugin for implementation + AuthMgrPlugin plugin = + (AuthMgrPlugin) mAuths.getPlugins().get(implname); + + if (plugin == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse( + ERROR, + new EAuthMgrPluginNotFound(CMS.getUserMessage(getLocale(req), + "CMS_AUTHENTICATION_AUTHMGR_NOT_FOUND", implname)).toString(), + null, resp); + return; + } + + // save old instance substore params in case new one fails. + + IAuthManager oldinst = + (IAuthManager) mAuths.get(id); + IConfigStore oldConfig = oldinst.getConfigStore(); + + String[] oldConfigParms = oldinst.getConfigParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.put(IAuthSubsystem.PROP_PLUGIN, + (String) oldConfig.get(IAuthSubsystem.PROP_PLUGIN)); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.length; i++) { + String key = oldConfigParms[i]; + Object val = oldConfig.get(key); + + if (val != null) { + saveParams.put(key, (String) val); + } + } + } + + // on to the new instance. + + // remove old substore. + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_AUTH_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + instancesConfig.removeSubStore(id); + + // create new substore. + + String[] configParams = mAuths.getConfigParams(implname); + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(IAuthSubsystem.PROP_PLUGIN, implname); + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + String key = configParams[i]; + String val = req.getParameter(key); + + if (val != null) { + substore.put(key, val); + } + } + } + + // Instantiate an object for new implementation + + String className = plugin.getClassPath(); + IAuthManager newMgrInst = null; + + try { + newMgrInst = (IAuthManager) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // cleanup + restore(instancesConfig, id, saveParams); + sendResponse( + ERROR, + new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL", + className)).toString(), + null, resp); + return; + } catch (InstantiationException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + restore(instancesConfig, id, saveParams); + sendResponse( + ERROR, + new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL", + className)).toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + restore(instancesConfig, id, saveParams); + sendResponse( + ERROR, + new EAuthException(CMS.getUserMessage(getLocale(req), "CMS_AUTHENTICATION_LOAD_CLASS_FAIL", + className)).toString(), + null, resp); + return; + } + + // initialize the authentication manager + + try { + newMgrInst.init(id, implname, substore); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // don't commit in this case and cleanup the new substore. + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + + // initialized ok. commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // clean up. + restore(instancesConfig, id, saveParams); + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // commited ok. replace instance. + + mAuths.add(id, newMgrInst); + + mAuths.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_MGR_REPL", id)); + + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_AUTH, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + // convenience routine. + private static void restore(IConfigStore store, + String id, NameValuePairs saveParams) { + store.removeSubStore(id); + IConfigStore rstore = store.makeSubStore(id); + + for (String key : saveParams.keySet()) { + String value = saveParams.get(key); + + if (value != null) + rstore.put(key, value); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/AuthCredentials.java b/base/common/src/com/netscape/cms/servlet/admin/AuthCredentials.java new file mode 100644 index 000000000..69cfd9aaf --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/AuthCredentials.java @@ -0,0 +1,109 @@ +// --- 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.admin; + +import java.util.Enumeration; +import java.util.Hashtable; + +import com.netscape.certsrv.authentication.IAuthCredentials; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; + +/** + * Authentication Credentials as input to the authMgr + * <P> + * + * @version $Revision$, $Date$ + */ +public class AuthCredentials implements IAuthCredentials { + /** + * + */ + private static final long serialVersionUID = -6938644716486895814L; + private Hashtable<String, Object> authCreds = null; + // Inserted by bskim + private IArgBlock argblk = null; + + // Insert end + + public AuthCredentials() { + authCreds = new Hashtable<String, Object>(); + } + + /** + * sets a credential with credential name and the credential + * + * @param name credential name + * @param cred credential + * @exception com.netscape.certsrv.base.EBaseException NullPointerException + */ + public void set(String name, Object cred) throws EBaseException { + if (cred == null) { + throw new EBaseException("AuthCredentials.set()"); + } + + authCreds.put(name, cred); + } + + /** + * returns the credential to which the specified name is mapped in this + * credential set + * + * @param name credential name + * @return the named authentication credential + */ + public Object get(String name) { + return authCreds.get(name); + } + + /** + * removes the name and its corresponding credential from this + * credential set. This method does nothing if the named + * credential is not in the credential set. + * + * @param name credential name + */ + public void delete(String name) { + authCreds.remove(name); + } + + /** + * returns an enumeration of the credential names in this credential + * set. Use the Enumeration methods on the returned object to + * fetch the elements sequentially. + * + * @return an enumeration of the names in this credential set + * @see java.util.Enumeration + */ + public Enumeration<String> getElements() { + return authCreds.keys(); + } + + // Inserted by bskim + public void setArgBlock(IArgBlock blk) { + argblk = blk; + return; + } + + // Insert end + + public IArgBlock getArgBlock() { + return argblk; + } + // Insert end +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java new file mode 100644 index 000000000..e7b32e844 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java @@ -0,0 +1,1582 @@ +// --- 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.admin; + +import java.io.File; +import java.io.IOException; +import java.net.UnknownHostException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.ca.ICMSCRLExtensions; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequestListener; +import com.netscape.cmsutil.util.Utils; + +/** + * A class representings an administration servlet for Certificate + * Authority. This servlet is responsible to serve CA + * administrative operations such as configuration parameter + * updates. + * + * @version $Revision$, $Date$ + */ +public class CAAdminServlet extends AdminServlet { + + /** + * + */ + private static final long serialVersionUID = 6200983242040946840L; + + public final static String PROP_EMAIL_TEMPLATE = "emailTemplate"; + + private final static String INFO = "CAAdminServlet"; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE = + "LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE_3"; + + private ICertificateAuthority mCA = null; + protected static final String PROP_ENABLED = "enabled"; + + /** + * Constructs CA servlet. + */ + public CAAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mCA = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP request. Each request is authenticated to + * the authenticate manager. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + //get all operational flags + String op = req.getParameter(Constants.OP_TYPE); + String scope = req.getParameter(Constants.OP_SCOPE); + + //check operational flags + if ((op == null) || (scope == null)) { + sendResponse(1, "Invalid Protocol", null, resp); + return; + } + + super.authenticate(req); + + try { + AUTHZ_RES_NAME = "certServer.ca.configuration"; + if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) { + try { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + getExtendedPluginInfo(req, resp); + return; + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + } + } + + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GENERAL)) + getGeneralConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CONNECTOR)) + getConnectorConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CRLIPS)) + getCRLIPsConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CRL)) + getCRLConfig(req, resp); + else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP)) + getNotificationReqCompConfig(req, resp); + else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP)) + getNotificationRevCompConfig(req, resp); + else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) + getNotificationRIQConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CRLEXTS_RULES)) + getCRLExtsConfig(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GENERAL)) + setGeneralConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CONNECTOR)) + setConnectorConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CRLIPS)) + setCRLIPsConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CRL)) + setCRLConfig(req, resp); + else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP)) + setNotificationReqCompConfig(req, resp); + else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP)) + setNotificationRevCompConfig(req, resp); + else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) + setNotificationRIQConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CRLEXTS_RULES)) + setCRLExtsConfig(req, resp); + } else if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_CRLEXTS_RULES)) + listCRLExtsConfig(req, resp); + else if (scope.equals(ScopeDef.SC_CRLIPS)) + listCRLIPsConfig(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_CRLIPS)) + addCRLIPsConfig(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_CRLIPS)) + deleteCRLIPsConfig(req, resp); + } else { + sendResponse(1, "Unknown operation", null, resp); + } + } catch (Exception e) { + sendResponse(1, e.toString(), null, resp); + return; + } + } + + /*========================================================== + * private methods + *==========================================================*/ + + /* + * handle request completion (cert issued) notification config requests + */ + private void getNotificationCompConfig(HttpServletRequest req, + HttpServletResponse resp, IConfigStore rc) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + params.put(name, rc.getString(name, "")); + } + + params.put(Constants.PR_ENABLE, + rc.getString(PROP_ENABLED, Constants.FALSE)); + sendResponse(SUCCESS, null, params, resp); + } + + private void getNotificationRevCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore config = mCA.getConfigStore(); + IConfigStore nc = + config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE); + IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_REVOKED_SUBSTORE); + + getNotificationCompConfig(req, resp, rc); + } + + private void getNotificationReqCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore config = mCA.getConfigStore(); + IConfigStore nc = + config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE); + IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_ISSUED_SUBSTORE); + + getNotificationCompConfig(req, resp, rc); + } + + /* + * handle getting request in queue notification config info + */ + private void getNotificationRIQConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + IConfigStore config = mCA.getConfigStore(); + IConfigStore nc = + config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(ICertificateAuthority.PROP_REQ_IN_Q_SUBSTORE); + + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + params.put(name, riq.getString(name, "")); + } + + params.put(Constants.PR_ENABLE, + riq.getString(PROP_ENABLED, Constants.FALSE)); + sendResponse(SUCCESS, null, params, resp); + } + + /* + * handle setting request in queue notification config info + */ + private void setNotificationRIQConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore config = mCA.getConfigStore(); + IConfigStore nc = + config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(ICertificateAuthority.PROP_REQ_IN_Q_SUBSTORE); + + //set rest of the parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + String val = req.getParameter(name); + + // if it's emailTemplate, check to see if the path exists + if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) { + File template = new File(val); + + if ((!template.exists()) || (!template.canRead()) + || (template.isDirectory())) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PATH")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PATH"), + null, resp); + return; + } + } + riq.putString(name, val); + mCA.getRequestInQListener().set(name, val); + } + + // set enable flag + String enabledString = req.getParameter(Constants.PR_ENABLE); + + riq.putString(PROP_ENABLED, enabledString); + mCA.getRequestInQListener().set(PROP_ENABLED, enabledString); + + commit(true); + + sendResponse(SUCCESS, null, null, resp); + } + + /* + * handle setting request complete notification config info + */ + private void setNotificationCompConfig(HttpServletRequest req, + HttpServletResponse resp, IConfigStore rc, IRequestListener thisListener) throws ServletException, + IOException, EBaseException { + + //set rest of the parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + String val = req.getParameter(name); + + // if it's emailTemplate, check to see if the path exists + if (name.equalsIgnoreCase(PROP_EMAIL_TEMPLATE)) { + File template = new File(val); + + if ((!template.exists()) || (!template.canRead()) + || (template.isDirectory())) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PATH")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PATH"), + null, resp); + return; + } + } + rc.putString(name, val); + thisListener.set(name, val); + } + + // set enable flag + String enabledString = req.getParameter(Constants.PR_ENABLE); + + rc.putString(PROP_ENABLED, enabledString); + thisListener.set(PROP_ENABLED, enabledString); + + commit(true); + + sendResponse(SUCCESS, null, null, resp); + } + + private void setNotificationRevCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore config = mCA.getConfigStore(); + IConfigStore nc = + config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_REVOKED_SUBSTORE); + + setNotificationCompConfig(req, resp, rc, mCA.getCertRevokedListener()); + } + + private void setNotificationReqCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore config = mCA.getConfigStore(); + IConfigStore nc = + config.getSubStore(ICertificateAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(ICertificateAuthority.PROP_CERT_ISSUED_SUBSTORE); + + setNotificationCompConfig(req, resp, rc, mCA.getCertIssuedListener()); + + } + + private void listCRLIPsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = ips.nextElement(); + + if (ip != null) { + String ipId = ip.getId(); + + if (ipId != null && ipId.length() > 0) + params.put(ipId, ip.getDescription()); + params.put(ipId + "." + Constants.PR_ENABLED, + (Boolean.valueOf(ip.isCRLIssuingPointEnabled())).toString()); + } + } + + sendResponse(SUCCESS, null, params, resp); + } + + private void getCRLIPsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + String id = req.getParameter(Constants.RS_ID); + + if (id != null && id.length() > 0) { + ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(id); + + if (ip != null) { + + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + String value = ""; + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.PR_ENABLED)) { + if (ip.isCRLIssuingPointEnabled()) { + value = Constants.TRUE; + } else { + value = Constants.FALSE; + } + } + if (name.equals(Constants.PR_ID)) + value = id; + if (name.equals(Constants.PR_DESCRIPTION)) + value = ip.getDescription(); + if (name.equals(Constants.PR_CLASS)) + value = ip.getClass().getName(); + + params.put(name, value); + } + } + } + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Add CRL issuing points configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions, + * frequency, CRL format) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void addCRLIPsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + + String ipId = req.getParameter(Constants.PR_ID); + + if (ipId == null || ipId.length() == 0) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, "Missing CRL IP name", null, resp); + return; + } + params.put(Constants.PR_ID, ipId); + + String desc = req.getParameter(Constants.PR_DESCRIPTION); + + if (desc == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, "Missing CRL IP description", null, resp); + return; + } + params.put(Constants.PR_DESCRIPTION, desc); + + String sEnable = req.getParameter(Constants.PR_ENABLED); + boolean enable = true; + + if (sEnable != null && sEnable.length() > 0 && + sEnable.equalsIgnoreCase(Constants.FALSE)) { + enable = false; + params.put(Constants.PR_ENABLED, Constants.FALSE); + } else { + params.put(Constants.PR_ENABLED, Constants.TRUE); + } + + IConfigStore crlSubStore = + mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE); + Enumeration<String> crlNames = crlSubStore.getSubStoreNames(); + + while (crlNames.hasMoreElements()) { + String name = crlNames.nextElement(); + + if (ipId.equals(name)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, ipId + " CRL IP already exists", null, resp); + return; + } + } + if (!mCA.addCRLIssuingPoint(crlSubStore, ipId, enable, desc)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, "Cannot add or edit CRL IP", null, resp); + return; + } + commit(true); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Set CRL issuing points configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions, + * frequency, CRL format) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void setCRLIPsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + + String ipId = req.getParameter(Constants.PR_ID); + + if (ipId == null || ipId.length() == 0) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, "Missing CRL IP name", null, resp); + return; + } + params.put(Constants.PR_ID, ipId); + + String desc = req.getParameter(Constants.PR_DESCRIPTION); + + if (desc == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, "Missing CRL IP description", null, resp); + return; + } + params.put(Constants.PR_DESCRIPTION, desc); + + String sEnable = req.getParameter(Constants.PR_ENABLED); + boolean enable = true; + + if (sEnable != null && sEnable.length() > 0 && + sEnable.equalsIgnoreCase(Constants.FALSE)) { + enable = false; + params.put(Constants.PR_ENABLED, Constants.FALSE); + } else { + params.put(Constants.PR_ENABLED, Constants.TRUE); + } + + IConfigStore crlSubStore = + mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE); + boolean done = false; + Enumeration<String> crlNames = crlSubStore.getSubStoreNames(); + + while (crlNames.hasMoreElements()) { + String name = crlNames.nextElement(); + + if (ipId.equals(name)) { + ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId); + + if (ip != null) { + ip.setDescription(desc); + ip.enableCRLIssuingPoint(enable); + } + IConfigStore c = crlSubStore.getSubStore(ipId); + + if (c != null) { + c.putString(Constants.PR_DESCRIPTION, desc); + c.putString(Constants.PR_ENABLED, + (enable) ? Constants.TRUE : Constants.FALSE); + } + done = true; + break; + } + } + if (!done) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, "Missing CRL IP " + ipId, null, resp); + return; + } + commit(true); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Delete CRL issuing points configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions, + * frequency, CRL format) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void deleteCRLIPsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + + String id = req.getParameter(Constants.RS_ID); + + if (id != null && id.length() > 0) { + IConfigStore crlSubStore = + mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE); + boolean done = false; + Enumeration<String> crlNames = crlSubStore.getSubStoreNames(); + + while (crlNames.hasMoreElements()) { + String name = crlNames.nextElement(); + + if (id.equals(name)) { + mCA.deleteCRLIssuingPoint(crlSubStore, id); + done = true; + break; + } + } + if (!done) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, "Missing CRL IP " + id, null, resp); + return; + } + commit(true); + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void getCRLExtsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + String ipId = null; + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + ipId = name; + } + if (ipId == null || ipId.length() <= 0) { + ipId = ICertificateAuthority.PROP_MASTER_CRL; + } + + ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId); + ICMSCRLExtensions crlExts = ip.getCRLExtensions(); + String id = req.getParameter(Constants.RS_ID); + + if (id != null) { + params = crlExts.getConfigParams(id); + } + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Delete CRL extensions configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions, + * frequency, CRL format) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void setCRLExtsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + + String ipId = req.getParameter(Constants.PR_ID); + + if (ipId == null || ipId.length() <= 0) { + ipId = ICertificateAuthority.PROP_MASTER_CRL; + } + + ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId); + ICMSCRLExtensions crlExts = ip.getCRLExtensions(); + + IConfigStore config = mCA.getConfigStore(); + IConfigStore crlsSubStore = + config.getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(ipId); + IConfigStore crlExtsSubStore = + crlSubStore.getSubStore(ICertificateAuthority.PROP_CRLEXT_SUBSTORE); + + String id = req.getParameter(Constants.RS_ID); + + if (id != null) { + IConfigStore crlExtSubStore = crlExtsSubStore.getSubStore(id); + + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_CRLEXT_IMPL_NAME)) + continue; + if (name.equals("RULENAME")) + continue; + String value = req.getParameter(name); + + params.put(name, value); + } + crlExts.setConfigParams(id, params, crlExtSubStore); + commit(true); + ip.clearCRLCache(); + ip.updateCRLCacheRepository(); + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void listCRLExtsConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + String id = req.getParameter(Constants.PR_ID); + + if (id == null || id.length() <= 0) { + id = ICertificateAuthority.PROP_MASTER_CRL; + } + + IConfigStore config = mCA.getConfigStore(); + IConfigStore crlsSubStore = config.getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(id); + IConfigStore crlExtsSubStore = crlSubStore.getSubStore(ICertificateAuthority.PROP_CRLEXT_SUBSTORE); + + if (crlExtsSubStore != null) { + Enumeration<String> enumExts = crlExtsSubStore.getSubStoreNames(); + + while (enumExts.hasMoreElements()) { + String extName = enumExts.nextElement(); + boolean crlExtEnabled = false; + IConfigStore crlExtSubStore = crlExtsSubStore.getSubStore(extName); + Enumeration<String> properties = crlExtSubStore.getPropertyNames(); + + while (properties.hasMoreElements()) { + String name = properties.nextElement(); + + if (name.equals(Constants.PR_ENABLE)) { + crlExtEnabled = crlExtSubStore.getBoolean(name, false); + } + } + params.put(extName, extName + ";visible;" + ((crlExtEnabled) ? "enabled" : "disabled")); + } + } + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * retrieve extended plugin info such as brief description, + * type info from CRL extensions + */ + private void getExtendedPluginInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + int colon = id.indexOf(':'); + + String implType = id.substring(0, colon); + String implName = id.substring(colon + 1); + + NameValuePairs params = + getExtendedPluginInfo(getLocale(req), implType, implName); + + sendResponse(SUCCESS, null, params, resp); + } + + private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) { + IExtendedPluginInfo ext_info = null; + Object impl = null; + + String ipId = null; + String name = null; + + Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints(); + if (ips.hasMoreElements()) { + ICRLIssuingPoint ip = ips.nextElement(); + if (ip != null) { + ipId = ip.getId(); + } + } + if (ipId != null) { + ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(ipId); + ICMSCRLExtensions crlExts = ip.getCRLExtensions(); + name = crlExts.getClassPath(implName); + } + if (name != null) { + impl = getClassByNameAsExtendedPluginInfo(name); + } + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + } + + return nvps; + } + + /** + * Set CRL configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE used when configuring CRL profile (extensions, + * frequency, CRL format) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void setCRLConfig(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + + String id = req.getParameter(Constants.RS_ID); + + if (id == null || id.length() <= 0 || + id.equals(Constants.RS_ID_CONFIG)) { + id = ICertificateAuthority.PROP_MASTER_CRL; + } + ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(id); + + //Save New Settings to the config file + IConfigStore config = mCA.getConfigStore(); + IConfigStore crlsSubStore = config.getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(id); + + //set reset of the parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + String value = req.getParameter(name); + + params.put(name, value); + crlSubStore.putString(name, value); + } + boolean noRestart = ip.updateConfig(params); + + commit(true); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + if (noRestart) + sendResponse(SUCCESS, null, null, resp); + else + sendResponse(RESTART, null, null, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_CRL_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void getCRLConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + String id = req.getParameter(Constants.RS_ID); + + if (id == null || id.length() <= 0 || + id.equals(Constants.RS_ID_CONFIG)) { + id = ICertificateAuthority.PROP_MASTER_CRL; + } + IConfigStore crlsSubStore = + mCA.getConfigStore().getSubStore(ICertificateAuthority.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(id); + + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + params.put(name, crlSubStore.getString(name, "")); + } + + getSigningAlgConfig(params); + sendResponse(SUCCESS, null, params, resp); + } + + private void getConnectorConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore caConfig = mCA.getConfigStore(); + IConfigStore connectorConfig = caConfig.getSubStore("connector"); + IConfigStore caConnectorConfig = null; + + if (isKRAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("KRA"); + } else if (isCLAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("CLA"); + } + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + NameValuePairs params = new NameValuePairs(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = enum1.nextElement(); + + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.OP_TYPE)) + continue; + + params.put(name, caConnectorConfig.getString(name, "")); + } + } + sendResponse(SUCCESS, null, params, resp); + } + + private void setConnectorConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore caConfig = mCA.getConfigStore(); + IConfigStore connectorConfig = caConfig.getSubStore("connector"); + IConfigStore caConnectorConfig = null; + + // String nickname = CMS.getServerCertNickname(); + + if (isKRAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("KRA"); + } else if (isCLAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("CLA"); + } + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = enum1.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + /* + if (name.equals("nickName")) { + caConnectorConfig.putString(name, nickname); + continue; + } + */ + if (name.equals("host")) { + try { + Utils.checkHost(req.getParameter("host")); + } catch (UnknownHostException e) { + sendResponse(ERROR, "Unknown Host " + req.getParameter("host"), null, resp); + return; + } + } + caConnectorConfig.putString(name, req.getParameter(name)); + } + } + + commit(true); + sendResponse(RESTART, null, null, resp); + } + + private boolean isKRAConnector(HttpServletRequest req) { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + + if (key.equals("RS_ID")) { + String val = req.getParameter(key); + + if (val.equals("Data Recovery Manager Connector")) + return true; + else + return false; + } + } + return false; + } + + private boolean isCLAConnector(HttpServletRequest req) { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + + if (key.equals("RS_ID")) { + String val = req.getParameter(key); + + if (val.equals("Clone Master Manager Connector")) + return true; + else + return false; + } + } + return false; + } + + private void getGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + String value = "false"; + + /* + ISubsystem eeGateway = + SubsystemRegistry.getInstance().get("eeGateway"); + if (eeGateway != null) { + IConfigStore eeConfig = eeGateway.getConfigStore(); + if (eeConfig != null) + value = eeConfig.getString("enabled", "true"); + String ocspValue = "true"; + ocspValue = eeConfig.getString("enableOCSP", "true"); + params.add(Constants.PR_OCSP_ENABLED, ocspValue); + } + params.add(Constants.PR_EE_ENABLED, value); + */ + + IConfigStore caConfig = mCA.getConfigStore(); + + value = caConfig.getString(ICertificateAuthority.PROP_ENABLE_PAST_CATIME, "false"); + params.put(Constants.PR_VALIDITY, value); + + getSigningAlgConfig(params); + getSerialConfig(params); + getMaxSerialConfig(params); + + sendResponse(SUCCESS, null, params, resp); + } + + private void getSigningAlgConfig(NameValuePairs params) { + params.put(Constants.PR_DEFAULT_ALGORITHM, + mCA.getDefaultAlgorithm()); + String[] algorithms = mCA.getCASigningAlgorithms(); + StringBuffer algorStr = new StringBuffer(); + + for (int i = 0; i < algorithms.length; i++) { + if (i == 0) + algorStr.append(algorithms[i]); + else { + algorStr.append(":"); + algorStr.append(algorithms[i]); + } + } + params.put(Constants.PR_ALL_ALGORITHMS, algorStr.toString()); + } + + private void getSerialConfig(NameValuePairs params) { + params.put(Constants.PR_SERIAL, + mCA.getStartSerial()); + } + + private void getMaxSerialConfig(NameValuePairs params) { + params.put(Constants.PR_MAXSERIAL, + mCA.getMaxSerial()); + } + + private void setGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + /* + ISubsystem eeGateway = + SubsystemRegistry.getInstance().get("eeGateway"); + */ + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + boolean restart = false; + + //mCA.setMaxSerial(""); + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_EE_ENABLED)) { + + /* + if (eeConfig != null) { + if (((EEGateway)eeGateway).isEnabled() && + value.equals("false") || + !((EEGateway)eeGateway).isEnabled() && + value.equals("true")) { + restart=true;; + } + eeConfig.putString("enabled", value); + } + */ + } else if (key.equals(Constants.PR_VALIDITY)) { + mCA.setValidity(value); + } else if (key.equals(Constants.PR_DEFAULT_ALGORITHM)) { + mCA.setDefaultAlgorithm(value); + } else if (key.equals(Constants.PR_SERIAL)) { + mCA.setStartSerial(value); + } else if (key.equals(Constants.PR_MAXSERIAL)) { + mCA.setMaxSerial(value); + } + } + + commit(true); + if (restart) + sendResponse(RESTART, null, null, resp); + else + sendResponse(SUCCESS, null, null, resp); + } + + private void log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER, + level, "CAAdminServlet: " + msg); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java new file mode 100644 index 000000000..3a2ae0a11 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java @@ -0,0 +1,3449 @@ +// --- 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.admin; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.KeyPair; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.PQGParams; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.util.ConsolePasswordCallback; +import org.mozilla.jss.util.PasswordCallback; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.cert.ICrossCertPairSubsystem; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.security.ICryptoSubsystem; +import com.netscape.certsrv.security.ISigningUnit; +import com.netscape.certsrv.security.KeyCertData; +import com.netscape.certsrv.selftests.EMissingSelfTestException; +import com.netscape.certsrv.selftests.ESelfTestException; +import com.netscape.certsrv.selftests.ISelfTest; +import com.netscape.certsrv.selftests.ISelfTestSubsystem; +import com.netscape.certsrv.tks.ITKSAuthority; +import com.netscape.cmsutil.util.Cert; +import com.netscape.cmsutil.util.Utils; +import com.netscape.symkey.SessionKey; + +/** + * A class representings an administration servlet. This + * servlet is responsible to serve Certificate Server + * level administrative operations such as configuration + * parameter updates. + * + * @version $Revision$, $Date$ + */ +public final class CMSAdminServlet extends AdminServlet { + + /** + * + */ + private static final long serialVersionUID = 714370238027440050L; + private final static String INFO = "CMSAdminServlet"; + private final static String BEGIN_HEADER = "-----BEGIN CERTIFICATE-----"; + private final static String END_HEADER = "-----END CERTIFICATE-----"; + + private final static String PROP_DB = "dbs"; + private final static String PROP_SMTP = "smtp"; + private final static String PROP_RADM = "radm"; + private final static String PROP_GATEWAY = "cmsgateway"; + private final static String PROP_INTERNAL_DB = "internaldb"; + + private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + private final static String LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION = + "LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION_3"; + private final static String LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY = + "LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY_3"; + private final static String LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC = + "LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC_3"; + private final static String LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION = + "LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION_2"; + private final static String LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION = + "LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION_3"; + + // CMS must be instantiated before this admin servlet. + + /** + * Constructs CA servlet. + */ + public CMSAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP request. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + try { + super.authenticate(req); + } catch (IOException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"), + null, resp); + return; + } + + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + try { + AUTHZ_RES_NAME = "certServer.general.configuration"; + if (scope.equals(ScopeDef.SC_PLATFORM)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + getEnv(req, resp); + return; + } + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_LDAP)) + getDBConfig(req, resp); + else if (scope.equals(ScopeDef.SC_SMTP)) + readSMTPConfig(req, resp); + else if (scope.equals(ScopeDef.SC_STAT)) + readStat(req, resp); + else if (scope.equals(ScopeDef.SC_ENCRYPTION)) + readEncryption(req, resp); + else if (scope.equals(ScopeDef.SC_TOKEN)) + getAllTokenNames(req, resp); + else if (scope.equals(ScopeDef.SC_SUBJECT_NAME)) + getSubjectName(req, resp); + else if (scope.equals(ScopeDef.SC_GET_NICKNAMES)) + getAllNicknames(req, resp); + else if (scope.equals(ScopeDef.SC_CERT_PRETTY_PRINT)) + getCertPrettyPrint(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_LDAP)) + setDBConfig(req, resp); + else if (scope.equals(ScopeDef.SC_SMTP)) + modifySMTPConfig(req, resp); + else if (scope.equals(ScopeDef.SC_TASKS)) + performTasks(req, resp); + else if (scope.equals(ScopeDef.SC_ENCRYPTION)) + modifyEncryption(req, resp); + else if (scope.equals(ScopeDef.SC_ISSUE_IMPORT_CERT)) + issueImportCert(req, resp); + else if (scope.equals(ScopeDef.SC_INSTALL_CERT)) + installCert(req, resp); + else if (scope.equals(ScopeDef.SC_IMPORT_CROSS_CERT)) + importXCert(req, resp); + else if (scope.equals(ScopeDef.SC_DELETE_CERTS)) + deleteCerts(req, resp); + else if (scope.equals(ScopeDef.SC_TRUST)) + trustCACert(req, resp); + else if (scope.equals(ScopeDef.SC_TOKEN_LOGON)) + loggedInToken(req, resp); + else if (scope.equals(ScopeDef.SC_ROOTCERT_TRUSTBIT)) + setRootCertTrust(req, resp); + } else if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_SUBSYSTEM)) + readSubsystem(req, resp); + else if (scope.equals(ScopeDef.SC_CA_CERTLIST)) + getCACerts(req, resp); + else if (scope.equals(ScopeDef.SC_ALL_CERTLIST)) + getAllCertsManage(req, resp); + else if (scope.equals(ScopeDef.SC_USERCERTSLIST)) + getUserCerts(req, resp); + else if (scope.equals(ScopeDef.SC_TKSKEYSLIST)) + getTKSKeys(req, resp); + else if (scope.equals(ScopeDef.SC_TOKEN)) + getAllTokenNames(req, resp); + else if (scope.equals(ScopeDef.SC_ROOTCERTSLIST)) + getRootCerts(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "delete"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_ROOTCERTSLIST)) { + deleteRootCert(req, resp); + } else if (scope.equals(ScopeDef.SC_USERCERTSLIST)) { + deleteUserCert(req, resp); + } + } else if (op.equals(OpDef.OP_PROCESS)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_CERT_REQUEST)) + getCertRequest(req, resp); + else if (scope.equals(ScopeDef.SC_SUBJECT_NAME)) + processSubjectName(req, resp); + else if (scope.equals(ScopeDef.SC_CERTINFO)) + getCertInfo(req, resp); + else if (scope.equals(ScopeDef.SC_CERT_PRETTY_PRINT)) + getCertPrettyPrint(req, resp); + else if (scope.equals(ScopeDef.SC_ROOTCERT_TRUSTBIT)) + getRootCertTrustBit(req, resp); + else if (scope.equals(ScopeDef.SC_TOKEN_STATUS)) + checkTokenStatus(req, resp); + else if (scope.equals(ScopeDef.SC_SELFTESTS)) + runSelfTestsOnDemand(req, resp); + else if (scope.equals(ScopeDef.SC_TKSKEYSLIST)) + createMasterKey(req, resp); + } else if (op.equals(OpDef.OP_VALIDATE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_SUBJECT_NAME)) + validateSubjectName(req, resp); + else if (scope.equals(ScopeDef.SC_KEY_LENGTH)) + validateKeyLength(req, resp); + else if (scope.equals(ScopeDef.SC_CERTIFICATE_EXTENSION)) + validateCertExtension(req, resp); + else if (scope.equals(ScopeDef.SC_KEY_CURVENAME)) + validateCurveName(req, resp); + } + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), + null, resp); + return; + } catch (Exception e) { + StringWriter sw = new StringWriter(); + + e.printStackTrace(new PrintWriter(sw)); + + sendResponse(1, "operation failure", null, resp); + return; + } + } + + private void getEnv(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + if (File.separator.equals("\\")) + params.put(Constants.PR_NT, Constants.TRUE); + else + params.put(Constants.PR_NT, Constants.FALSE); + + sendResponse(SUCCESS, null, params, resp); + } + + private void getAllTokenNames(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_TOKEN_LIST, jssSubSystem.getTokenList()); + + sendResponse(SUCCESS, null, params, resp); + } + + private void getAllNicknames(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + params.put(Constants.PR_ALL_NICKNAMES, jssSubSystem.getAllCerts()); + + sendResponse(SUCCESS, null, params, resp); + } + + private boolean isSubsystemInstalled(String subsystem) { + Enumeration<ISubsystem> e = CMS.getSubsystems(); + + while (e.hasMoreElements()) { + ISubsystem sys = (ISubsystem) e.nextElement(); + + //get subsystem type + if ((sys instanceof IKeyRecoveryAuthority) && + subsystem.equals("kra")) + return true; + else if ((sys instanceof IRegistrationAuthority) && + subsystem.equals("ra")) + return true; + else if ((sys instanceof ICertificateAuthority) && + subsystem.equals("ca")) + return true; + else if ((sys instanceof IOCSPAuthority) && + subsystem.equals("ocsp")) + return true; + } + + return false; + } + + private void readEncryption(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + Enumeration<ISubsystem> e = CMS.getSubsystems(); + boolean isCAInstalled = false; + boolean isRAInstalled = false; + boolean isKRAInstalled = false; + + while (e.hasMoreElements()) { + ISubsystem sys = (ISubsystem) e.nextElement(); + + //get subsystem type + if (sys instanceof IKeyRecoveryAuthority) + isKRAInstalled = true; + else if (sys instanceof IRegistrationAuthority) + isRAInstalled = true; + else if (sys instanceof ICertificateAuthority) + isCAInstalled = true; + + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String caTokenName = ""; + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_CIPHER_VERSION, + jssSubSystem.getCipherVersion()); + params.put(Constants.PR_CIPHER_FORTEZZA, jssSubSystem.isCipherFortezza()); + params.put(Constants.PR_CIPHER_PREF, jssSubSystem.getCipherPreferences()); + + String tokenList = jssSubSystem.getTokenList(); + + String tokenNewList = ""; + StringTokenizer tokenizer = new StringTokenizer(tokenList, ","); + + while (tokenizer.hasMoreElements()) { + String tokenName = (String) tokenizer.nextElement(); + String certs = jssSubSystem.getCertListWithoutTokenName(tokenName); + + if (certs.equals("")) + continue; + if (tokenNewList.equals("")) + tokenNewList = tokenNewList + tokenName; + else + tokenNewList = tokenNewList + "," + tokenName; + tokenName = escapeString(tokenName); + params.put(Constants.PR_TOKEN_PREFIX + tokenName, certs); + } + + params.put(Constants.PR_TOKEN_LIST, tokenNewList); + + if (isCAInstalled) { + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getSigningUnit(); + + caTokenName = signingUnit.getTokenName(); + + if (caTokenName.equals(jssSubSystem.getInternalTokenName())) + caTokenName = Constants.PR_INTERNAL_TOKEN; + + String caNickName = signingUnit.getNickname(); + + //params.add(Constants.PR_CERT_CA, caTokenName+","+caNickName); + params.put(Constants.PR_CERT_CA, getCertNickname(caNickName)); + } + + if (isRAInstalled) { + IRegistrationAuthority ra = (IRegistrationAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_RA); + String raNickname = ra.getNickname(); + + params.put(Constants.PR_CERT_RA, getCertNickname(raNickname)); + } + + if (isKRAInstalled) { + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + String kraNickname = kra.getNickname(); + + params.put(Constants.PR_CERT_TRANS, getCertNickname(kraNickname)); + } + + String nickName = CMS.getServerCertNickname(); + + params.put(Constants.PR_CERT_SERVER, getCertNickname(nickName)); + + sendResponse(SUCCESS, null, params, resp); + } + + private String escapeString(String name) { + StringTokenizer tokenizer = new StringTokenizer(name, " "); + StringBuffer tokenname = new StringBuffer(); + + if (tokenizer.countTokens() == 1) + return name; + while (tokenizer.hasMoreElements()) { + if (tokenizer.countTokens() == 1) + tokenname.append((String) tokenizer.nextElement()); + else { + tokenname.append((String) tokenizer.nextElement()); + tokenname.append("%20"); + } + } + + return tokenname.toString(); + } + + private String getCertNickname(String nickName) { + if (!nickName.equals("")) { + StringTokenizer tokenizer = new StringTokenizer(nickName, ":"); + String tokenName = ""; + + if (tokenizer.countTokens() > 1) { + tokenName = (String) tokenizer.nextElement(); + } else { + tokenName = Constants.PR_INTERNAL_TOKEN; + } + return tokenName + "," + ((String) tokenizer.nextElement()); + } + return ""; + } + + /** + * Modify encryption configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION used when configuring encryption (cert settings and SSL + * cipher preferences) + * </ul> + * + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException failed to modify encryption configuration + */ + private void modifyEncryption(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + NameValuePairs params = new NameValuePairs(); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + jssSubSystem.getInternalTokenName(); + Enumeration<ISubsystem> e = CMS.getSubsystems(); + boolean isCAInstalled = false; + boolean isRAInstalled = false; + boolean isKRAInstalled = false; + + while (e.hasMoreElements()) { + ISubsystem sys = (ISubsystem) e.nextElement(); + + //get subsystem type + if (sys instanceof IKeyRecoveryAuthority) + isKRAInstalled = true; + else if (sys instanceof IRegistrationAuthority) + isRAInstalled = true; + else if (sys instanceof ICertificateAuthority) + isCAInstalled = true; + } + + ICertificateAuthority ca = null; + IRegistrationAuthority ra = null; + IKeyRecoveryAuthority kra = null; + + if (isCAInstalled) + ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA); + if (isRAInstalled) + ra = (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA); + if (isKRAInstalled) + kra = (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + + boolean isCACert = true; + + while (enum1.hasMoreElements()) { + String name = (String) enum1.nextElement(); + String val = req.getParameter(name); + + if (name.equals(Constants.PR_CIPHER_PREF)) { + jssSubSystem.setCipherPreferences(val); + } else if (name.equals(Constants.PR_CERT_CA)) { + ISigningUnit signingUnit = ca.getSigningUnit(); + + if ((val != null) && (!val.equals(""))) { + StringTokenizer tokenizer = new StringTokenizer(val, ","); + + if (tokenizer.countTokens() != 2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_INVALID_UI_INFO")); + } + + String tokenName = (String) tokenizer.nextElement(); + String nickName = (String) tokenizer.nextElement(); + + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN)) { + tokenName = jssSubSystem.getInternalTokenName(); + } else { + nickName = tokenName + ":" + nickName; + } + + isCACert = jssSubSystem.isCACert(nickName); + if (isCACert) { + signingUnit.updateConfig(nickName, tokenName); + } else + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_NOT_CA_CERT")); + } + } else if (name.equals(Constants.PR_CERT_RA)) { + if ((val != null) && (!val.equals(""))) { + String nickName = getCertConfigNickname(val); + + ra.setNickname(nickName); + } + } else if (name.equals(Constants.PR_CERT_TRANS)) { + if ((val != null) && (!val.equals(""))) { + String nickName = getCertConfigNickname(val); + + kra.setNickname(nickName); + } + } else if (name.equals(Constants.PR_CERT_SERVER)) { + if ((val != null) && (!val.equals(""))) { + String nickName = getCertConfigNickname(val); + + modifyRADMCert(nickName); + modifyAgentGatewayCert(nickName); + if (isRAInstalled) + modifyEEGatewayCert(ra, nickName); + if (isCAInstalled) + modifyCAGatewayCert(ca, nickName); + } + } + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(RESTART, null, params, resp); + mConfig.commit(true); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ENCRYPTION, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private String getCertConfigNickname(String val) throws EBaseException { + StringTokenizer tokenizer = new StringTokenizer(val, ","); + + if (tokenizer.countTokens() != 2) { + throw new EBaseException(CMS.getLogMessage("BASE_INVALID_UI_INFO")); + } + String tokenName = (String) tokenizer.nextElement(); + + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN)) + tokenName = ""; + else + tokenName = tokenName + ":"; + return (tokenName + (String) tokenizer.nextElement()); + } + + private void modifyRADMCert(String nickName) { + CMS.setServerCertNickname(nickName); + + /* + RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance(); + HTTPService httpsService = raAdmin.getHttpsService(); + httpsService.setNickName(nickName); + */ + } + + private void modifyAgentGatewayCert(String nickName) { + CMS.setServerCertNickname(nickName); + + /* + AgentGateway gateway = (AgentGateway)mReg.get(AgentGateway.ID); + HTTPService httpsService = gateway.getHttpsService(); + httpsService.setNickName(nickName); + */ + } + + private void modifyEEGatewayCert(IRegistrationAuthority ra, String nickName) { + CMS.setServerCertNickname(nickName); + + /* + HTTPSubsystem eeGateway = ra.getHTTPSubsystem(); + HTTPService httpsService = eeGateway.getHttpsService(); + httpsService.setNickName(nickName); + */ + } + + private void modifyCAGatewayCert(ICertificateAuthority ca, String nickName) { + CMS.setServerCertNickname(nickName); + + /* + HTTPSubsystem caGateway = ca.getHTTPSubsystem(); + HTTPService httpsService = caGateway.getHttpsService(); + httpsService.setNickName(nickName); + */ + } + + /** + * Performs Server Tasks: RESTART/STOP operation + */ + private void performTasks(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String restart = req.getParameter(Constants.PR_SERVER_RESTART); + String stop = req.getParameter(Constants.PR_SERVER_STOP); + NameValuePairs params = new NameValuePairs(); + + if (restart != null) { + //XXX Uncommented afetr watchdog is implemented + sendResponse(SUCCESS, null, params, resp); + //mServer.restart(); + return; + } + + if (stop != null) { + //XXX Send response first then shutdown + sendResponse(SUCCESS, null, params, resp); + CMS.shutdown(); + return; + } + + sendResponse(ERROR, "Unknown operation", null, resp); + + } + + /** + * Reads subsystems that server has loaded with. + */ + private void readSubsystem(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + Enumeration<ISubsystem> e = CMS.getSubsystems(); + + while (e.hasMoreElements()) { + String type = ""; + ISubsystem sys = (ISubsystem) e.nextElement(); + + //get subsystem type + if (sys instanceof IKeyRecoveryAuthority) + type = Constants.PR_KRA_INSTANCE; + if (sys instanceof IRegistrationAuthority) + type = Constants.PR_RA_INSTANCE; + if (sys instanceof ICertificateAuthority) + type = Constants.PR_CA_INSTANCE; + if (sys instanceof IOCSPAuthority) + type = Constants.PR_OCSP_INSTANCE; + if (sys instanceof ITKSAuthority) + type = Constants.PR_TKS_INSTANCE; + if (!type.trim().equals("")) + params.put(sys.getId(), type); + } + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Reads server statistics. + */ + private void readStat(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + IConfigStore cs = CMS.getConfigStore(); + try { + String installdate = cs.getString(Constants.PR_STAT_INSTALLDATE, ""); + params.put(Constants.PR_STAT_INSTALLDATE, installdate); + } catch (Exception e) { + } + + try { + String version = cs.getString(Constants.PR_STAT_VERSION, ""); + params.put(Constants.PR_STAT_VERSION, version); + } catch (Exception e) { + } + + try { + String instanceId = cs.getString(Constants.PR_STAT_INSTANCEID, ""); + params.put(Constants.PR_STAT_INSTANCEID, instanceId); + } catch (Exception e) { + } + + params.put(Constants.PR_STAT_STARTUP, + (new Date(CMS.getStartupTime())).toString()); + params.put(Constants.PR_STAT_TIME, + (new Date(System.currentTimeMillis())).toString()); + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Modifies database information. + */ + private void setDBConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore dbConfig = mConfig.getSubStore(PROP_INTERNAL_DB); + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + + if (key.equals(Constants.OP_TYPE)) + continue; + if (key.equals(Constants.RS_ID)) + continue; + if (key.equals(Constants.OP_SCOPE)) + continue; + + dbConfig.putString(key, req.getParameter(key)); + } + + sendResponse(RESTART, null, null, resp); + mConfig.commit(true); + } + + /** + * Create Master Key + */ + private void createMasterKey(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + String newKeyName = null, selectedToken = null; + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + + if (name.equals(Constants.PR_KEY_LIST)) { + newKeyName = req.getParameter(name); + } + if (name.equals(Constants.PR_TOKEN_LIST)) { + selectedToken = req.getParameter(name); + } + + } + if (selectedToken != null && newKeyName != null) { + SessionKey.GenMasterKey(selectedToken, newKeyName); // check for errors + CMS.getConfigStore().putString("tks.defaultSlot", selectedToken); + String masterKeyPrefix = CMS.getConfigStore().getString("tks.master_key_prefix", null); + + SessionKey.SetDefaultPrefix(masterKeyPrefix); + params.put(Constants.PR_KEY_LIST, newKeyName); + params.put(Constants.PR_TOKEN_LIST, selectedToken); + } + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Reads secmod.db + */ + private void getTKSKeys(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + + if (name.equals(Constants.PR_TOKEN_LIST)) { + String selectedToken = req.getParameter(name); + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + CryptoToken token = null; + CryptoManager mCryptoManager = null; + try { + mCryptoManager = CryptoManager.getInstance(); + } catch (Exception e2) { + } + + if (!jssSubSystem.isTokenLoggedIn(selectedToken)) { + PasswordCallback cpcb = new ConsolePasswordCallback(); + while (true) { + try { + token = mCryptoManager.getTokenByName(selectedToken); + token.login(cpcb); + break; + } catch (Exception e3) { + //log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_SECURITY_INCORRECT_PWD")); + continue; + } + } + } + // String symKeys = new String("key1,key2"); + String symKeys = SessionKey.ListSymmetricKeys(selectedToken); + params.put(Constants.PR_TOKEN_LIST, symKeys); + + } + } + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Reads database information. + */ + private void getDBConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore dbConfig = mConfig.getSubStore(PROP_DB); + IConfigStore ldapConfig = dbConfig.getSubStore("ldap"); + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_SECURE_PORT_ENABLED)) + params.put(name, ldapConfig.getString(name, "Constants.FALSE")); + else + params.put(name, ldapConfig.getString(name, "")); + } + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Modifies SMTP configuration. + */ + private void modifySMTPConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + // XXX + IConfigStore sConfig = mConfig.getSubStore(PROP_SMTP); + + String host = req.getParameter(Constants.PR_SERVER_NAME); + + if (host != null) + sConfig.putString("host", host); + + String port = req.getParameter(Constants.PR_PORT); + + if (port != null) + sConfig.putString("port", port); + + commit(true); + + sendResponse(SUCCESS, null, null, resp); + } + + /** + * Reads SMTP configuration. + */ + private void readSMTPConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore dbConfig = mConfig.getSubStore(PROP_SMTP); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_SERVER_NAME, + dbConfig.getString("host")); + params.put(Constants.PR_PORT, + dbConfig.getString("port")); + sendResponse(SUCCESS, null, params, resp); + } + + private void loggedInToken(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + String tokenName = ""; + String pwd = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_TOKEN_NAME)) { + tokenName = value; + } else if (key.equals(Constants.PR_TOKEN_PASSWD)) { + pwd = value; + } + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + jssSubSystem.loggedInToken(tokenName, pwd); + + /* Do a "PUT" of the new pw to the watchdog" */ + CMS.putPasswordCache(tokenName, pwd); + sendResponse(SUCCESS, null, null, resp); + } + + private void checkTokenStatus(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + String key = ""; + String value = ""; + + while (enum1.hasMoreElements()) { + key = (String) enum1.nextElement(); + value = req.getParameter(key); + if (key.equals(Constants.PR_TOKEN_NAME)) { + break; + } + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + boolean status = jssSubSystem.isTokenLoggedIn(value); + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_LOGGED_IN, "" + status); + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Retrieve a certificate request + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC used when asymmetric keys are generated + * </ul> + * + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException failed to retrieve certificate request + */ + private void getCertRequest(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditPublicKey = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + String tokenName = Constants.PR_INTERNAL_TOKEN_NAME; + String keyType = ""; + int keyLength = 512; + String subjectName = ""; + String certType = Constants.PR_CA_SIGNING_CERT; + String dir = ""; + String pathname = ""; + String otherNickname = ""; + String keyCurveName = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_TOKEN_NAME)) { + if (!value.equals(Constants.PR_INTERNAL_TOKEN)) + tokenName = value; + } else if (key.equals(Constants.PR_KEY_LENGTH)) { + keyLength = Integer.parseInt(value); + } else if (key.equals(Constants.PR_KEY_TYPE)) { + keyType = value; + } else if (key.equals(Constants.RS_ID)) { + certType = value; + } else if (key.equals(Constants.PR_SUBJECT_NAME)) { + subjectName = value; + } else if (key.equals(Constants.PR_NICKNAME)) { + otherNickname = value; + } else if (key.equals(Constants.PR_KEY_CURVENAME)) { + keyCurveName = value; + } + } + + pathname = mConfig.getString("instanceRoot", "") + + File.separator + "conf" + File.separator; + dir = pathname; + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + KeyPair keypair = null; + PQGParams pqgParams = null; + String nickname = ""; + + // other cert and has the existing key + if (certType.equals(Constants.PR_OTHER_CERT) && keyType.equals("")) + nickname = otherNickname; + else if (!certType.equals(Constants.PR_OTHER_CERT)) + nickname = getNickname(certType); + + String nicknameWithoutTokenName = ""; + + if (nickname != null && !nickname.equals("")) { + int index = nickname.indexOf(":"); + + nicknameWithoutTokenName = nickname; + if (index >= 0) + nicknameWithoutTokenName = nickname.substring(index + 1); + } + + if (keyType.equals("")) { + if (nickname.equals("")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC, + auditSubjectID, + ILogger.FAILURE, + auditPublicKey); + + audit(auditMessage); + + throw new EBaseException( + CMS.getLogMessage("BASE_CERT_NOT_FOUND")); + } + keypair = jssSubSystem.getKeyPair(nickname); + } else { + if (keyType.equals("ECC")) { + // get ECC keypair + keypair = jssSubSystem.getECCKeyPair(tokenName, keyCurveName, certType); + } else { //DSA or RSA + if (keyType.equals("DSA")) + pqgParams = jssSubSystem.getPQG(keyLength); + keypair = jssSubSystem.getKeyPair(tokenName, keyType, keyLength, pqgParams); + } + } + + // reset the "auditPublicKey" + auditPublicKey = auditPublicKey(keypair); + + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + pathname = pathname + File.separator + "cacsr.txt"; + if (!keyType.equals("")) + setCANewnickname(tokenName, nicknameWithoutTokenName); + } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) { + pathname = pathname + File.separator + "racsr.txt"; + if (!keyType.equals("")) + setRANewnickname(tokenName, nicknameWithoutTokenName); + } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) { + pathname = pathname + File.separator + "ocspcsr.txt"; + if (!keyType.equals("")) + setOCSPNewnickname(tokenName, nicknameWithoutTokenName); + } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) { + pathname = pathname + File.separator + "kracsr.txt"; + if (!keyType.equals("")) + setKRANewnickname(tokenName, nicknameWithoutTokenName); + } else if (certType.equals(Constants.PR_SERVER_CERT)) { + pathname = pathname + File.separator + "sslcsr.txt"; + if (!keyType.equals("")) + setAgentNewnickname(tokenName, nicknameWithoutTokenName); + } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) { + pathname = pathname + File.separator + "sslcsrradm.txt"; + if (!keyType.equals("")) + setRADMNewnickname(tokenName, nicknameWithoutTokenName); + } else if (certType.equals(Constants.PR_OTHER_CERT)) { + pathname = pathname + File.separator + "othercsr.txt"; + } + String certReq = jssSubSystem.getCertRequest(subjectName, keypair); + + params.put(Constants.PR_CSR, certReq); + params.put(Constants.PR_CERT_REQUEST_DIR, dir); + PrintStream ps = new PrintStream(new FileOutputStream(pathname)); + + ps.println(certReq); + ps.close(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC, + auditSubjectID, + ILogger.SUCCESS, + auditPublicKey); + + audit(auditMessage); + + mConfig.commit(true); + sendResponse(SUCCESS, null, params, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC, + auditSubjectID, + ILogger.FAILURE, + auditPublicKey); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC, + auditSubjectID, + ILogger.FAILURE, + auditPublicKey); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_KEY_GEN_ASYMMETRIC, + // auditSubjectID, + // ILogger.FAILURE, + // auditPublicKey ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void setCANewnickname(String tokenName, String nickname) + throws EBaseException { + ICertificateAuthority ca = (ICertificateAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getSigningUnit(); + + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) + signingUnit.setNewNickName(nickname); + else { + if (tokenName.equals("") && nickname.equals("")) + signingUnit.setNewNickName(""); + else + signingUnit.setNewNickName(tokenName + ":" + nickname); + } + } + + private String getCANewnickname() throws EBaseException { + ICertificateAuthority ca = (ICertificateAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getSigningUnit(); + + return signingUnit.getNewNickName(); + } + + private void setRANewnickname(String tokenName, String nickname) + throws EBaseException { + IRegistrationAuthority ra = (IRegistrationAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_RA); + + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) + ra.setNewNickName(nickname); + else { + if (tokenName.equals("") && nickname.equals("")) + ra.setNewNickName(""); + else + ra.setNewNickName(tokenName + ":" + nickname); + } + } + + private String getRANewnickname() throws EBaseException { + IRegistrationAuthority ra = (IRegistrationAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_RA); + + return ra.getNewNickName(); + } + + private void setOCSPNewnickname(String tokenName, String nickname) + throws EBaseException { + IOCSPAuthority ocsp = (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP); + + if (ocsp != null) { + ISigningUnit signingUnit = ocsp.getSigningUnit(); + + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) + signingUnit.setNewNickName(nickname); + else { + if (tokenName.equals("") && nickname.equals("")) + signingUnit.setNewNickName(""); + else + signingUnit.setNewNickName(tokenName + ":" + nickname); + } + } else { + ICertificateAuthority ca = (ICertificateAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getOCSPSigningUnit(); + + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) + signingUnit.setNewNickName(nickname); + else { + if (tokenName.equals("") && nickname.equals("")) + signingUnit.setNewNickName(""); + else + signingUnit.setNewNickName(tokenName + ":" + nickname); + } + } + } + + private String getOCSPNewnickname() throws EBaseException { + IOCSPAuthority ocsp = (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP); + + if (ocsp != null) { + ISigningUnit signingUnit = ocsp.getSigningUnit(); + + return signingUnit.getNewNickName(); + } else { + ICertificateAuthority ca = (ICertificateAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getOCSPSigningUnit(); + + return signingUnit.getNewNickName(); + } + } + + private void setKRANewnickname(String tokenName, String nickname) + throws EBaseException { + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) + kra.setNewNickName(nickname); + else { + if (tokenName.equals("") && nickname.equals("")) + kra.setNewNickName(""); + else + kra.setNewNickName(tokenName + ":" + nickname); + } + } + + private String getKRANewnickname() throws EBaseException { + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + + return kra.getNewNickName(); + } + + private void setRADMNewnickname(String tokenName, String nickName) + throws EBaseException { + CMS.setServerCertNickname(tokenName, nickName); + + /* + RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance(); + HTTPService httpsService = raAdmin.getHttpsService(); + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) + httpsService.setNewNickName(nickName); + else { + if (tokenName.equals("") && nickName.equals("")) + httpsService.setNewNickName(""); + else + httpsService.setNewNickName(tokenName+":"+nickName); + } + */ + } + + private String getRADMNewnickname() + throws EBaseException { + // assuming the nickname does not change. + return CMS.getServerCertNickname(); + + /* + RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance(); + HTTPService httpsService = raAdmin.getHttpsService(); + return httpsService.getNewNickName(); + */ + } + + private void setAgentNewnickname(String tokenName, String nickName) + throws EBaseException { + CMS.setServerCertNickname(tokenName, nickName); + + /* + AgentGateway gateway = (AgentGateway)mReg.get(AgentGateway.ID); + HTTPService httpsService = gateway.getHttpsService(); + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) + httpsService.setNewNickName(nickName); + else { + if (tokenName.equals("") && nickName.equals("")) + httpsService.setNewNickName(""); + else + httpsService.setNewNickName(tokenName+":"+nickName); + } + */ + } + + private String getAgentNewnickname() + throws EBaseException { + // assuming the nickname does not change. + return CMS.getServerCertNickname(); + + /* + AgentGateway gateway = (AgentGateway)mReg.get(AgentGateway.ID); + HTTPService httpsService = gateway.getHttpsService(); + return httpsService.getNewNickName(); + */ + } + + /** + * Issue import certificate + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Certificate Setup Wizard" is used to + * import CA certs into the certificate database + * </ul> + * + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException failed to issue an import certificate + */ + private void issueImportCert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + String tokenName = Constants.PR_INTERNAL_TOKEN_NAME; + String keyType = "RSA"; + KeyCertData properties = new KeyCertData(); + + String newtokenname = null; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (!key.equals("pathname")) { + if (key.equals(Constants.PR_TOKEN_NAME)) + newtokenname = value; + properties.put(key, value); + } + } + + String certType = (String) properties.get(Constants.RS_ID); + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + ICertificateAuthority ca = (ICertificateAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ICertificateRepository repository = + (ICertificateRepository) ca.getCertificateRepository(); + ISigningUnit signingUnit = ca.getSigningUnit(); + String oldtokenname = null; + //this is the old nick name + String nickname = getNickname(certType); + String nicknameWithoutTokenName = ""; + String oldcatokenname = signingUnit.getTokenName(); + String canickname = getNickname(Constants.PR_CA_SIGNING_CERT); + String canicknameWithoutTokenName = ""; + + int index = nickname.indexOf(":"); + + if (index == -1) { + nicknameWithoutTokenName = nickname; + oldtokenname = Constants.PR_INTERNAL_TOKEN_NAME; + } else if (index > 0 && (index < (nickname.length() - 1))) { + nicknameWithoutTokenName = nickname.substring(index + 1); + oldtokenname = nickname.substring(0, index); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_CERT_NOT_FOUND")); + } + + if (newtokenname == null) + newtokenname = oldtokenname; + index = canickname.indexOf(":"); + if (index == -1) { + canicknameWithoutTokenName = canickname; + } else if (index > 0 && (index < (canickname.length() - 1))) { + canicknameWithoutTokenName = canickname.substring(index + 1); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_CERT_NOT_FOUND")); + } + + //xxx renew ca ,use old issuer? + properties.setIssuerName( + jssSubSystem.getCertSubjectName(oldcatokenname, + canicknameWithoutTokenName)); + + KeyPair pair = null; + + if (nickname.equals("")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_CERT_NOT_FOUND")); + } + + //xxx set to old nickname? + properties.setCertNickname(nickname); + if (!certType.equals(Constants.PR_CA_SIGNING_CERT)) { + CertificateExtensions exts = jssSubSystem.getExtensions( + oldcatokenname, canicknameWithoutTokenName); + + properties.setCAExtensions(exts); + } + + KeyPair caKeyPair = null; + String defaultSigningAlg = null; + String defaultOCSPSigningAlg = null; + + if (properties.getHashType() != null) { + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + defaultSigningAlg = properties.getHashType(); + } + if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) { + defaultOCSPSigningAlg = properties.getHashType(); + } + } + + // create a new CA certificate or ssl server cert + if (properties.getKeyCurveName() != null) { //new ECC + CMS.debug("CMSAdminServlet: issueImportCert: generating ECC keys"); + pair = jssSubSystem.getECCKeyPair(properties); + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) + caKeyPair = pair; + } else if (properties.getKeyLength() != null) { //new RSA or DSA + keyType = properties.getKeyType(); + String keyLen = properties.getKeyLength(); + + if (keyType.equals("DSA")) { + @SuppressWarnings("unused") + PQGParams pqgParams = + jssSubSystem.getCAPQG(Integer.parseInt(keyLen), mConfig); // check for errors + //properties.put(Constants.PR_PQGPARAMS, pqgParams); + } + pair = jssSubSystem.getKeyPair(properties); + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) + caKeyPair = pair; + // renew the CA certificate or ssl server cert + } else { + pair = jssSubSystem.getKeyPair(nickname); + // should get it from the CA signing certificate + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + updateCASignature(nickname, properties, jssSubSystem); + caKeyPair = pair; + defaultSigningAlg = signingUnit.getDefaultAlgorithm(); + } + + /* + String alg = jssSubSystem.getSignatureAlgorithm(nickname); + SignatureAlgorithm sigAlg = SigningUnit.mapAlgorithmToJss(alg); + properties.setSignatureAlgorithm(sigAlg); + properties.setAlgorithmId( + jssSubSystem.getAlgorithmId(alg, mConfig)); + */ + } + + String alg = properties.getSignedBy(); + if (!certType.equals(Constants.PR_CA_SIGNING_CERT)) { + caKeyPair = jssSubSystem.getKeyPair(canickname); + updateCASignature(canickname, properties, jssSubSystem); + } else if (alg != null) { + // self signed CA signing cert, new keys + // value provided for signedBy + SignatureAlgorithm sigAlg = Cert.mapAlgorithmToJss(alg); + properties.setSignatureAlgorithm(sigAlg); + properties.setAlgorithmId(jssSubSystem.getAlgorithmId(alg, mConfig)); + } + + if (pair == null) + CMS.debug("CMSAdminServlet: issueImportCert: key pair is null"); + + BigInteger nextSerialNo = repository.getNextSerialNumber(); + + properties.setSerialNumber(nextSerialNo); + properties.setKeyPair(pair); + properties.setConfigFile(mConfig); + // properties.put(Constants.PR_CA_KEYPAIR, pair); + properties.put(Constants.PR_CA_KEYPAIR, caKeyPair); + + X509CertImpl signedCert = + jssSubSystem.getSignedCert(properties, certType, + caKeyPair.getPrivate()); + + if (signedCert == null) + CMS.debug("CMSAdminServlet: issueImportCert: signedCert is null"); + + /* bug 600124 + try { + jssSubSystem.deleteTokenCertificate(nickname, pathname); + } catch (Throwable e) { + //skip it + } + */ + + boolean nicknameChanged = false; + + //xxx import cert with nickname without token name? + //jss adds the token prefix!!! + //log(ILogger.LL_DEBUG,"import as alias"+ nicknameWithoutTokenName); + try { + CMS.debug("CMSAdminServlet: issueImportCert: Importing cert: " + nicknameWithoutTokenName); + jssSubSystem.importCert(signedCert, nicknameWithoutTokenName, + certType); + } catch (EBaseException e) { + // if it fails, let use a different nickname to try + Date now = new Date(); + String newNickname = nicknameWithoutTokenName + + "-" + now.getTime(); + + CMS.debug("CMSAdminServlet: issueImportCert: Importing cert with nickname: " + newNickname); + jssSubSystem.importCert(signedCert, newNickname, + certType); + nicknameWithoutTokenName = newNickname; + nicknameChanged = true; + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = newNickname; + } else { + nickname = tokenName + ":" + newNickname; + } + } + + ICertRecord certRecord = repository.createCertRecord( + signedCert.getSerialNumber(), + signedCert, null); + + repository.addCertificateRecord(certRecord); + + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + try { + X509CertInfo certInfo = (X509CertInfo) signedCert.get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + CertificateExtensions extensions = (CertificateExtensions) + certInfo.get(X509CertInfo.EXTENSIONS); + + if (extensions != null) { + BasicConstraintsExtension basic = + (BasicConstraintsExtension) + extensions.get(BasicConstraintsExtension.NAME); + + if (basic == null) + log(CMS.getLogMessage("ADMIN_SRVLT_BASIC_CONSTRAIN_NULL")); + else { + Integer pathlen = (Integer) + basic.get(BasicConstraintsExtension.PATH_LEN); + int num = pathlen.intValue(); + + if (num == 0) + ca.setBasicConstraintMaxLen(num); + else if (num > 0) { + num = num - 1; + ca.setBasicConstraintMaxLen(num); + } + } + } else + log(CMS.getLogMessage("ADMIN_SRVLT_CERT_NO_EXT")); + } catch (Exception eee) { + log("CMSAdminServlet: Exception caught: " + eee.toString()); + } + } + + CMS.debug("CMSAdminServlet: oldtoken:" + oldtokenname + + " newtoken:" + newtokenname + " nickname:" + nickname); + if ((newtokenname != null && + !newtokenname.equals(oldtokenname)) || nicknameChanged) { + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + signingUnit.updateConfig(nicknameWithoutTokenName, + newtokenname); + } else { + signingUnit.updateConfig(newtokenname + ":" + + nicknameWithoutTokenName, + newtokenname); + } + } else if (certType.equals(Constants.PR_SERVER_CERT)) { + if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = nicknameWithoutTokenName; + } else { + nickname = newtokenname + ":" + + nicknameWithoutTokenName; + } + + //setRADMNewnickname("",""); + //modifyRADMCert(nickname); + modifyAgentGatewayCert(nickname); + if (isSubsystemInstalled("ra")) { + IRegistrationAuthority ra = + (IRegistrationAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_RA); + + modifyEEGatewayCert(ra, nickname); + } + if (isSubsystemInstalled("ca")) { + modifyCAGatewayCert(ca, nickname); + } + } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) { + if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = nicknameWithoutTokenName; + } else { + nickname = newtokenname + ":" + + nicknameWithoutTokenName; + } + + modifyRADMCert(nickname); + } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) { + if (ca != null) { + ISigningUnit ocspSigningUnit = ca.getOCSPSigningUnit(); + + if (newtokenname.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + ocspSigningUnit.updateConfig( + nicknameWithoutTokenName, newtokenname); + } else { + ocspSigningUnit.updateConfig(newtokenname + ":" + + nicknameWithoutTokenName, + newtokenname); + } + } + } + } + + // set signing algorithms if needed + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) + signingUnit.setDefaultAlgorithm(defaultSigningAlg); + + if (defaultOCSPSigningAlg != null) { + ISigningUnit ocspSigningUnit = ca.getOCSPSigningUnit(); + ocspSigningUnit.setDefaultAlgorithm(defaultOCSPSigningAlg); + } + + properties.clear(); + properties = null; + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + mConfig.commit(true); + sendResponse(SUCCESS, null, null, resp); + } catch (EBaseException eAudit1) { + CMS.debug("CMSAdminServlet: issueImportCert: EBaseException thrown: " + eAudit1.toString()); + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + CMS.debug("CMSAdminServlet: issueImportCert: IOException thrown: " + eAudit2.toString()); + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void updateCASignature(String nickname, KeyCertData properties, + ICryptoSubsystem jssSubSystem) throws EBaseException { + String alg = jssSubSystem.getSignatureAlgorithm(nickname); + SignatureAlgorithm sigAlg = Cert.mapAlgorithmToJss(alg); + + properties.setSignatureAlgorithm(sigAlg); + properties.setAlgorithmId( + jssSubSystem.getAlgorithmId(alg, mConfig)); + } + + /** + * Install certificates + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Certificate Setup Wizard" is used to + * import CA certs into the certificate database + * </ul> + * + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException failed to install a certificate + */ + private void installCert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String tokenName = Constants.PR_INTERNAL_TOKEN_NAME; + String pkcs = ""; + String certType = ""; + String nickname = ""; + String pathname = ""; + String serverRoot = ""; + String serverID = ""; + String certpath = ""; + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_PKCS10)) + pkcs = value; + else if (key.equals(Constants.RS_ID)) + certType = value; + else if (key.equals(Constants.PR_NICKNAME)) + nickname = value; + else if (key.equals("pathname")) + pathname = value; + else if (key.equals(Constants.PR_SERVER_ROOT)) + serverRoot = value; + else if (key.equals(Constants.PR_SERVER_ID)) + serverID = value; + else if (key.equals(Constants.PR_CERT_FILEPATH)) + certpath = value; + } + + try { + if (pkcs == null || pkcs.equals("")) { + if (certpath == null || certpath.equals("")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + EBaseException ex = new EBaseException( + CMS.getLogMessage("BASE_INVALID_FILE_PATH")); + + throw ex; + } else { + FileInputStream in = new FileInputStream(certpath); + BufferedReader d = + new BufferedReader(new InputStreamReader(in)); + String content = ""; + + pkcs = ""; + StringBuffer sb = new StringBuffer(); + while ((content = d.readLine()) != null) { + sb.append(content); + sb.append("\n"); + } + + pkcs = sb.toString(); + if (d != null) { + d.close(); + } + pkcs = pkcs.substring(0, pkcs.length() - 1); + } + } + } catch (IOException ee) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException( + CMS.getLogMessage("BASE_OPEN_FILE_FAILED")); + } + + pkcs = pkcs.trim(); + pathname = serverRoot + File.separator + serverID + + File.separator + "config" + File.separator + pathname; + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + //String nickname = getNickname(certType); + String nicknameWithoutTokenName = ""; + + int index = nickname.indexOf(":"); + + if (index == -1) + nicknameWithoutTokenName = nickname; + else if (index > 0 && (index < (nickname.length() - 1))) { + tokenName = nickname.substring(0, index); + nicknameWithoutTokenName = nickname.substring(index + 1); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException( + CMS.getLogMessage("BASE_CERT_NOT_FOUND")); + } + + /* + if (certType.equals(Constants.PR_CA_SIGNING_CERT) || + certType.equals(Constants.PR_RA_SIGNING_CERT) || + certType.equals(Constants.PR_OCSP_SIGNING_CERT) || + certType.equals(Constants.PR_KRA_TRANSPORT_CERT) || + certType.equals(Constants.PR_SERVER_CERT) || + certType.equals(Constants.PR_SERVER_CERT_RADM)) { + String oldnickname = getNickname(certType); + try { + jssSubsystem.deleteTokenCertificate(oldnickname, + pathname); + //jssSubsystem.deleteTokenCertificate(nickname, + pathname); + } catch (EBaseException e) { + // skip it + } + } else { + try { + jssSubsystem.deleteTokenCertificate(nickname, pathname); + } catch (EBaseException e) { + // skip it + } + } + */ + + // 600124 - renewal of SSL crash the server + // we now do not delete previously installed certificates. + + // Same Subject | Same Nickname | Same Key | Legal + // ----------------------------------------------------------- + // 1. Yes Yes No Yes + // 2. Yes Yes Yes Yes + // 3. No No Yes Yes + // 4. No No No Yes + // 5. No Yes Yes No + // 6. No Yes No No + // 7. Yes No Yes No + // 8. Yes No No No + + // Based on above table, the following cases are permitted: + // Existing Key: + // (a) Same Subject & Same Nickname --- (2) + // (b) Different Subject & Different Nickname --- (3) + // (In order to support Case b., we need to use a different + // nickname). + // New Key: + // (c) Same Subject & Same Nickname --- (1) + // (d) Different Subject & Different Nickname --- (4) + // (In order to support Case b., we need to use a different + // nickname). + // + + CMS.debug("CMSAdminServlet.installCert(): About to try jssSubSystem.importCert: " + + nicknameWithoutTokenName); + try { + jssSubSystem.importCert(pkcs, nicknameWithoutTokenName, + certType); + } catch (EBaseException e) { + + boolean certFound = false; + + String eString = e.toString(); + if (eString.contains("Failed to find certificate that was just imported")) { + CMS.debug("CMSAdminServlet.installCert(): nickname=" + + nicknameWithoutTokenName + " TokenException: " + eString); + + X509Certificate cert = null; + try { + cert = CryptoManager.getInstance().findCertByNickname(nickname); + if (cert != null) { + certFound = true; + } + CMS.debug("CMSAdminServlet.installCert() Found cert just imported: " + nickname); + } catch (Exception ex) { + CMS.debug("CMSAdminServlet.installCert() Can't find cert just imported: " + ex.toString()); + } + } + + if (!certFound) { + // if it fails, let use a different nickname to try + Date now = new Date(); + String newNickname = nicknameWithoutTokenName + "-" + + now.getTime(); + + jssSubSystem.importCert(pkcs, newNickname, certType); + nicknameWithoutTokenName = newNickname; + if (tokenName.equals(Constants.PR_INTERNAL_TOKEN_NAME)) { + nickname = newNickname; + } else { + nickname = tokenName + ":" + newNickname; + } + CMS.debug("CMSAdminServlet: installCert(): After second install attempt following initial error: nickname=" + + nickname); + } + } + + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + ICertificateAuthority ca = + (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getSigningUnit(); + String signatureAlg = + jssSubSystem.getSignatureAlgorithm(nickname); + + signingUnit.setDefaultAlgorithm(signatureAlg); + setCANewnickname("", ""); + try { + CertificateExtensions extensions = null; + + if (nickname.equals(nicknameWithoutTokenName)) { + signingUnit.updateConfig(nickname, + Constants.PR_INTERNAL_TOKEN_NAME); + extensions = jssSubSystem.getExtensions( + Constants.PR_INTERNAL_TOKEN_NAME, nickname); + } else { + String tokenname1 = nickname.substring(0, index); + + signingUnit.updateConfig(nickname, tokenname1); + extensions = jssSubSystem.getExtensions(tokenname1, + nicknameWithoutTokenName); + } + if (extensions != null) { + BasicConstraintsExtension basic = + (BasicConstraintsExtension) + extensions.get(BasicConstraintsExtension.NAME); + + if (basic == null) + log(CMS.getLogMessage("ADMIN_SRVLT_BASIC_CONSTRAIN_NULL")); + else { + Integer pathlen = (Integer) + basic.get(BasicConstraintsExtension.PATH_LEN); + int num = pathlen.intValue(); + + if (num == 0) + ca.setBasicConstraintMaxLen(num); + else if (num > 0) { + num = num - 1; + ca.setBasicConstraintMaxLen(num); + } + } + } else { + log(CMS.getLogMessage("ADMIN_SRVLT_CERT_NO_EXT")); + } + } catch (Exception eee) { + log("CMSAdminServlet: Exception: " + eee.toString()); + } + } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) { + setRANewnickname("", ""); + IRegistrationAuthority ra = + (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA); + + ra.setNickname(nickname); + } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) { + setOCSPNewnickname("", ""); + IOCSPAuthority ocsp = + (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP); + + if (ocsp != null) { + ISigningUnit signingUnit = ocsp.getSigningUnit(); + + if (nickname.equals(nicknameWithoutTokenName)) { + signingUnit.updateConfig(nickname, + Constants.PR_INTERNAL_TOKEN_NAME); + } else { + String tokenname1 = nickname.substring(0, index); + + signingUnit.updateConfig(nickname, tokenname1); + } + } else { + ICertificateAuthority ca = + (ICertificateAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getOCSPSigningUnit(); + + if (nickname.equals(nicknameWithoutTokenName)) { + signingUnit.updateConfig(nickname, + Constants.PR_INTERNAL_TOKEN_NAME); + } else { + String tokenname1 = nickname.substring(0, index); + + signingUnit.updateConfig(nickname, tokenname1); + } + } + } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) { + setKRANewnickname("", ""); + IKeyRecoveryAuthority kra = + (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + + kra.setNickname(nickname); + } else if (certType.equals(Constants.PR_SERVER_CERT)) { + setAgentNewnickname("", ""); + //modifyRADMCert(nickname); + modifyAgentGatewayCert(nickname); + if (isSubsystemInstalled("ra")) { + IRegistrationAuthority ra = + (IRegistrationAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_RA); + + modifyEEGatewayCert(ra, nickname); + } + if (isSubsystemInstalled("ca")) { + ICertificateAuthority ca = + (ICertificateAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_CA); + + modifyCAGatewayCert(ca, nickname); + } + } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) { + setRADMNewnickname("", ""); + modifyRADMCert(nickname); + } + + boolean verified = CMS.verifySystemCertByNickname(nickname, null); + if (verified == true) { + CMS.debug("CMSAdminServlet: installCert(): verifySystemCertByNickname() succeeded:" + nickname); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + auditSubjectID, + ILogger.SUCCESS, + nickname); + + audit(auditMessage); + } else { + CMS.debug("CMSAdminServlet: installCert(): verifySystemCertByNickname() failed:" + nickname); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CIMC_CERT_VERIFICATION, + auditSubjectID, + ILogger.FAILURE, + nickname); + + audit(auditMessage); + } + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + mConfig.commit(true); + if (verified == true) { + sendResponse(SUCCESS, null, null, resp); + } else { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_CERT_VALIDATE_FAILED"), + null, resp); + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * For "importing" cross-signed cert into internal db for further + * cross pair matching and publishing + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Certificate Setup Wizard" is used to + * import a CA cross-signed certificate into the database + * </ul> + * + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException failed to import a cross-certificate pair + */ + private void importXCert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String b64Cert = ""; + String pathname = ""; + String serverRoot = ""; + String serverID = ""; + String certpath = ""; + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + NameValuePairs results = new NameValuePairs(); + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + // really should be PR_CERT_CONTENT + if (key.equals(Constants.PR_PKCS10)) + b64Cert = value; + else if (key.equals("pathname")) + pathname = value; + else if (key.equals(Constants.PR_SERVER_ROOT)) + serverRoot = value; + else if (key.equals(Constants.PR_SERVER_ID)) + serverID = value; + else if (key.equals(Constants.PR_CERT_FILEPATH)) + certpath = value; + } + + try { + if (b64Cert == null || b64Cert.equals("")) { + if (certpath == null || certpath.equals("")) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + EBaseException ex = new EBaseException( + CMS.getLogMessage("BASE_INVALID_FILE_PATH")); + + throw ex; + } else { + FileInputStream in = new FileInputStream(certpath); + BufferedReader d = + new BufferedReader(new InputStreamReader(in)); + String content = ""; + + b64Cert = ""; + StringBuffer sb = new StringBuffer(); + while ((content = d.readLine()) != null) { + sb.append(content); + sb.append("\n"); + } + b64Cert = sb.toString(); + if (d != null) { + d.close(); + } + b64Cert = b64Cert.substring(0, b64Cert.length() - 1); + } + } + } catch (IOException ee) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException( + CMS.getLogMessage("BASE_OPEN_FILE_FAILED")); + } + CMS.debug("CMSAdminServlet: got b64Cert"); + b64Cert = Cert.stripBrackets(b64Cert.trim()); + + // Base64 decode cert + byte[] bCert = null; + + try { + bCert = Utils.base64decode(b64Cert); + } catch (Exception e) { + CMS.debug("CMSAdminServlet: exception: " + e.toString()); + } + + pathname = serverRoot + File.separator + serverID + + File.separator + "config" + File.separator + pathname; + + ICrossCertPairSubsystem ccps = + (ICrossCertPairSubsystem) CMS.getSubsystem("CrossCertPair"); + + try { + //this will import into internal ldap crossCerts entry + ccps.importCert(bCert); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(1, "xcert importing failure:" + e.toString(), + null, resp); + return; + } + + try { + // this will publish all of the cross cert pairs from internal + // db to publishing directory, if turned on + ccps.publishCertPairs(); + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(1, "xcerts publishing failure:" + e.toString(), null, resp); + return; + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String content = jssSubSystem.getCertPrettyPrint(b64Cert, + super.getLocale(req)); + + results.put(Constants.PR_NICKNAME, "FBCA cross-signed cert"); + results.put(Constants.PR_CERT_CONTENT, content); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, results, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private String getNickname(String certType) throws EBaseException { + String nickname = ""; + + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + ICertificateAuthority ca = + (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getSigningUnit(); + + nickname = signingUnit.getNickname(); + } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) { + IOCSPAuthority ocsp = + (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP); + + if (ocsp == null) { + // this is a local CA service + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_CA); + ISigningUnit signingUnit = ca.getOCSPSigningUnit(); + + nickname = signingUnit.getNickname(); + } else { + ISigningUnit signingUnit = ocsp.getSigningUnit(); + + nickname = signingUnit.getNickname(); + } + } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) { + IRegistrationAuthority ra = + (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA); + + nickname = ra.getNickname(); + } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) { + IKeyRecoveryAuthority kra = + (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + + nickname = kra.getNickname(); + } else if (certType.equals(Constants.PR_SERVER_CERT)) { + nickname = CMS.getServerCertNickname(); + } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) { + nickname = CMS.getServerCertNickname(); + } + + return nickname; + } + + private void getCertInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + NameValuePairs results = new NameValuePairs(); + String pkcs = ""; + String path = ""; + String certType = ""; + String otherNickname = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_PKCS10)) { + pkcs = value; + } else if (key.equals(Constants.RS_ID)) { + certType = value; + } else if (key.equals(Constants.PR_CERT_FILEPATH)) { + path = value; + } else if (key.equals(Constants.PR_NICKNAME)) { + otherNickname = value; + } + } + + try { + if (pkcs == null || pkcs.equals("")) { + + if (path == null || path.equals("")) { + EBaseException ex = new EBaseException( + CMS.getLogMessage("BASE_INVALID_FILE_PATH")); + + throw ex; + } else { + FileInputStream in = new FileInputStream(path); + BufferedReader d = + new BufferedReader(new InputStreamReader(in)); + String content = ""; + + pkcs = ""; + StringBuffer sb = new StringBuffer(); + while ((content = d.readLine()) != null) { + sb.append(content); + sb.append("\n"); + } + pkcs = sb.toString(); + if (d != null) { + d.close(); + } + pkcs = pkcs.substring(0, pkcs.length() - 1); + } + } + } catch (IOException ee) { + throw new EBaseException(CMS.getLogMessage("BASE_OPEN_FILE_FAILED")); + } + + pkcs = pkcs.trim(); + int totalLen = pkcs.length(); + + if (pkcs.indexOf(BEGIN_HEADER) != 0 || + pkcs.indexOf(END_HEADER) != (totalLen - 25)) { + throw (new EBaseException(CMS.getLogMessage("BASE_INVALID_CERT_FORMAT"))); + } + + String nickname = ""; + + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + nickname = getCANewnickname(); + } else if (certType.equals(Constants.PR_RA_SIGNING_CERT)) { + nickname = getRANewnickname(); + } else if (certType.equals(Constants.PR_KRA_TRANSPORT_CERT)) { + nickname = getKRANewnickname(); + } else if (certType.equals(Constants.PR_SERVER_CERT)) { + nickname = getAgentNewnickname(); + } else if (certType.equals(Constants.PR_SERVER_CERT_RADM)) { + nickname = getRADMNewnickname(); + } else if (certType.equals(Constants.PR_OTHER_CERT)) { + nickname = otherNickname; + } else if (certType.equals(Constants.PR_OCSP_SIGNING_CERT)) { + nickname = getOCSPNewnickname(); + } + if (nickname.equals("")) + nickname = getNickname(certType); + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String content = jssSubSystem.getCertPrettyPrint(pkcs, + super.getLocale(req)); + + if (nickname != null && !nickname.equals("")) + results.put(Constants.PR_NICKNAME, nickname); + results.put(Constants.PR_CERT_CONTENT, content); + //results = jssSubSystem.getCertInfo(value); + + sendResponse(SUCCESS, null, results, resp); + } + + private void getCertPrettyPrint(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String nickname = ""; + String serialno = ""; + String issuername = ""; + Locale locale = super.getLocale(req); + NameValuePairs pairs = new NameValuePairs(); + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.OP_TYPE)) + continue; + if (key.equals(Constants.RS_ID)) + continue; + if (key.equals(Constants.OP_SCOPE)) + continue; + if (key.equals(Constants.PR_NICK_NAME)) { + nickname = value; + continue; + } + if (key.equals(Constants.PR_SERIAL_NUMBER)) { + serialno = value; + continue; + } + if (key.equals(Constants.PR_ISSUER_NAME)) { + issuername = value; + continue; + } + } + + String print = jssSubSystem.getCertPrettyPrintAndFingerPrint(nickname, + serialno, issuername, locale); + pairs.put(nickname, print); + + sendResponse(SUCCESS, null, pairs, resp); + } + + private void getRootCertTrustBit(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String nickname = ""; + String serialno = ""; + String issuername = ""; + NameValuePairs pairs = new NameValuePairs(); + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.OP_TYPE)) + continue; + if (key.equals(Constants.RS_ID)) + continue; + if (key.equals(Constants.OP_SCOPE)) + continue; + if (key.equals(Constants.PR_NICK_NAME)) { + nickname = value; + continue; + } + if (key.equals(Constants.PR_SERIAL_NUMBER)) { + serialno = value; + continue; + } + if (key.equals(Constants.PR_ISSUER_NAME)) { + issuername = value; + continue; + } + } + + String trustbit = jssSubSystem.getRootCertTrustBit(nickname, + serialno, issuername); + pairs.put(nickname, trustbit); + + sendResponse(SUCCESS, null, pairs, resp); + } + + private void getCACerts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + NameValuePairs pairs = jssSubSystem.getCACerts(); + + sendResponse(SUCCESS, null, pairs, resp); + } + + private void deleteRootCert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + int mindex = id.indexOf(":SERIAL#<"); + String nickname = id.substring(0, mindex); + String sstr1 = id.substring(mindex); + int lindex = sstr1.indexOf(">"); + String serialno = sstr1.substring(9, lindex); + String issuername = sstr1.substring(lindex + 1); + jssSubSystem.deleteRootCert(nickname, serialno, issuername); + sendResponse(SUCCESS, null, null, resp); + } + + private void deleteUserCert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + int mindex = id.indexOf(":SERIAL#<"); + String nickname = id.substring(0, mindex); + String sstr1 = id.substring(mindex); + int lindex = sstr1.indexOf(">"); + String serialno = sstr1.substring(9, lindex); + String issuername = sstr1.substring(lindex + 1); + jssSubSystem.deleteUserCert(nickname, serialno, issuername); + sendResponse(SUCCESS, null, null, resp); + } + + private void getRootCerts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + NameValuePairs pairs = jssSubSystem.getRootCerts(); + + sendResponse(SUCCESS, null, pairs, resp); + } + + private void getAllCertsManage(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + NameValuePairs pairs = jssSubSystem.getAllCertsManage(); + + sendResponse(SUCCESS, null, pairs, resp); + } + + private void getUserCerts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + NameValuePairs pairs = jssSubSystem.getUserCerts(); + sendResponse(SUCCESS, null, pairs, resp); + } + + private void deleteCerts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String nickname = ""; + String date = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.OP_TYPE)) + continue; + if (key.equals(Constants.RS_ID)) + continue; + if (key.equals(Constants.OP_SCOPE)) + continue; + int index = value.indexOf(";"); + + nickname = value.substring(0, index); + date = value.substring(index + 1); + // cant use this one now since jss doesnt have the interface to + // do it. + jssSubSystem.deleteCert(nickname, date); + // jssSubsystem.deleteCACert(nickname, date); + } + + sendResponse(SUCCESS, null, null, resp); + } + + private void validateSubjectName(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_SUBJECT_NAME)) { + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + jssSubSystem.isX500DN(value); + } + } + + sendResponse(SUCCESS, null, null, resp); + } + + private void validateKeyLength(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + sendResponse(SUCCESS, null, null, resp); + } + + private void validateCurveName(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + String curveName = null; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_KEY_CURVENAME)) { + curveName = value; + } + } + // check that the curvename is in the list of supported curves + String curveList = mConfig.getString("keys.ecc.curve.list", "nistp521"); + String[] curves = curveList.split(","); + boolean match = false; + for (int i = 0; i < curves.length; i++) { + if (curves[i].equals(curveName)) { + match = true; + } + } + if (!match) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ECC_CURVE_NAME")); + } + + sendResponse(SUCCESS, null, null, resp); + } + + private void validateCertExtension(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + String certExt = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(ConfigConstants.PR_CERTIFICATE_EXTENSION)) { + certExt = value; + break; + } + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + jssSubSystem.checkCertificateExt(certExt); + sendResponse(SUCCESS, null, null, resp); + } + + private void getSubjectName(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + String nickname = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.RS_ID)) { + nickname = getNickname(value); + break; + } + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String subjectName = jssSubSystem.getSubjectDN(nickname); + + params.put(Constants.PR_SUBJECT_NAME, subjectName); + sendResponse(SUCCESS, null, params, resp); + } + + private void processSubjectName(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + String nickname = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_NICKNAME)) { + nickname = value; + } + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String subjectName = jssSubSystem.getSubjectDN(nickname); + + params.put(Constants.PR_SUBJECT_NAME, subjectName); + sendResponse(SUCCESS, null, params, resp); + } + + public void setRootCertTrust(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String nickname = req.getParameter(Constants.PR_NICK_NAME); + String serialno = req.getParameter(Constants.PR_SERIAL_NUMBER); + String issuername = req.getParameter(Constants.PR_ISSUER_NAME); + String trust = req.getParameter("trustbit"); + + CMS.debug("CMSAdminServlet: setRootCertTrust()"); + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + try { + jssSubSystem.setRootCertTrust(nickname, serialno, issuername, trust); + } catch (EBaseException e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + // rethrow the specific exception to be handled later + throw e; + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } + + /** + * Establish trust of a CA certificate + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY used when "Manage Certificate" is used to edit + * the trustness of certs and deletion of certs + * </ul> + * + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException failed to establish CA certificate trust + */ + private void trustCACert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + CMS.debug("CMSAdminServlet: trustCACert()"); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String trust = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.RS_ID)) { + trust = value; + } else if (key.equals("certName0")) { + int index = value.indexOf(";"); + String nickname = value.substring(0, index); + String date = value.substring(index + 1); + + jssSubSystem.trustCert(nickname, date, trust); + } + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + //sendResponse(SUCCESS, null, null, resp); + sendResponse(RESTART, null, null, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_TRUSTED_PUBLIC_KEY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Execute all self tests specified to be run on demand. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION used when self tests are run on demand + * </ul> + * + * @exception EMissingSelfTestException a self test plugin instance + * property name was missing + * @exception ESelfTestException a self test is missing a required + * configuration parameter + * @exception IOException an input/output error has occurred + */ + private synchronized void + runSelfTestsOnDemand(HttpServletRequest req, + HttpServletResponse resp) + throws EMissingSelfTestException, + ESelfTestException, + IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + if (CMS.debugOn()) { + CMS.debug("CMSAdminServlet::runSelfTestsOnDemand():" + + " ENTERING . . ."); + } + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + String request = ""; + NameValuePairs results = new NameValuePairs(); + String content = ""; + String instanceName = null; + String instanceFullName = null; + String logMessage = null; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_RUN_SELFTESTS_ON_DEMAND)) { + request = value; + } + } + + ISelfTestSubsystem mSelfTestSubsystem = (ISelfTestSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_SELFTESTS); + + if ((request == null) || + (request.equals(""))) { + // self test plugin run on demand request parameter was missing + // log the error + logMessage = CMS.getLogMessage("SELFTESTS_RUN_ON_DEMAND_REQUEST", + getServletInfo(), + Constants.PR_RUN_SELFTESTS_ON_DEMAND + ); + + mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(), + logMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + // notify console of FAILURE + content += logMessage + + "\n"; + sendResponse(ERROR, content, null, resp); + + // raise an exception + throw new ESelfTestException(logMessage); + } + + // run all self test plugin instances (designated on-demand) + String[] selftests = mSelfTestSubsystem.listSelfTestsEnabledOnDemand(); + + if (selftests != null && selftests.length > 0) { + // log that execution of on-demand self tests has begun + logMessage = CMS.getLogMessage("SELFTESTS_RUN_ON_DEMAND", + getServletInfo()); + + mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(), + logMessage); + + // store this information for console notification + content += logMessage + + "\n"; + + for (int i = 0; i < selftests.length; i++) { + if (selftests[i] != null) { + instanceName = selftests[i].trim(); + instanceFullName = ISelfTestSubsystem.ID + + "." + + ISelfTestSubsystem.PROP_CONTAINER + + "." + + ISelfTestSubsystem.PROP_INSTANCE + + "." + + instanceName; + } else { + // self test plugin instance property name was missing + // log the error + logMessage = CMS.getLogMessage( + "SELFTESTS_PARAMETER_WAS_NULL", + getServletInfo()); + + mSelfTestSubsystem.log( + mSelfTestSubsystem.getSelfTestLogger(), + logMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + // notify console of FAILURE + content += logMessage + + "\n"; + sendResponse(ERROR, content, null, resp); + + // raise an exception + throw new EMissingSelfTestException(); + } + + ISelfTest test = (ISelfTest) + mSelfTestSubsystem.getSelfTest(instanceName); + + if (test == null) { + // self test plugin instance property name is not present + // log the error + logMessage = CMS.getLogMessage("SELFTESTS_MISSING_NAME", + getServletInfo(), + instanceFullName); + + mSelfTestSubsystem.log( + mSelfTestSubsystem.getSelfTestLogger(), + logMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + // notify console of FAILURE + content += logMessage + + "\n"; + sendResponse(ERROR, content, null, resp); + + // raise an exception + throw new EMissingSelfTestException(instanceFullName); + } + + try { + if (CMS.debugOn()) { + CMS.debug("CMSAdminServlet::runSelfTestsOnDemand():" + + " running \"" + + test.getSelfTestName() + + "\""); + } + + // store this information for console notification + content += "CMSAdminServlet::runSelfTestsOnDemand():" + + " running \"" + + test.getSelfTestName() + + "\" . . .\n"; + + test.runSelfTest(mSelfTestSubsystem.getSelfTestLogger()); + + // store this information for console notification + content += "COMPLETED SUCCESSFULLY\n"; + } catch (ESelfTestException e) { + // Check to see if the self test was critical: + if (mSelfTestSubsystem.isSelfTestCriticalOnDemand( + instanceName)) { + // log the error + logMessage = CMS.getLogMessage( + "SELFTESTS_RUN_ON_DEMAND_FAILED", + getServletInfo(), + instanceFullName); + + mSelfTestSubsystem.log( + mSelfTestSubsystem.getSelfTestLogger(), + logMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + // notify console of FAILURE + content += "FAILED WITH CRITICAL ERROR\n"; + content += logMessage + + "\n"; + sendResponse(ERROR, content, null, resp); + + // shutdown the system gracefully + CMS.shutdown(); + + return; + } else { + // store this information for console notification + content += "FAILED WITH NON-CRITICAL ERROR\n"; + } + } + } + + // log that execution of all "critical" on-demand self tests + // has completed "successfully" + logMessage = CMS.getLogMessage("SELFTESTS_RUN_ON_DEMAND_SUCCEEDED", + getServletInfo()); + mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(), + logMessage); + + // store this information for console notification + content += logMessage + + "\n"; + } else { + // log this fact + logMessage = CMS.getLogMessage("SELFTESTS_NOT_RUN_ON_DEMAND", + getServletInfo()); + + mSelfTestSubsystem.log(mSelfTestSubsystem.getSelfTestLogger(), + logMessage); + + // store this information for console notification + content += logMessage + + "\n"; + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.SUCCESS); + + audit(auditMessage); + + // notify console of SUCCESS + results.put(Constants.PR_RUN_SELFTESTS_ON_DEMAND_CLASS, + CMSAdminServlet.class.getName()); + results.put(Constants.PR_RUN_SELFTESTS_ON_DEMAND_CONTENT, + content); + sendResponse(SUCCESS, null, results, resp); + + if (CMS.debugOn()) { + CMS.debug("CMSAdminServlet::runSelfTestsOnDemand():" + + " EXITING."); + } + } catch (EMissingSelfTestException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (ESelfTestException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + } catch (IOException eAudit3) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SELFTESTS_EXECUTION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit3; + } + } + + public void log(int level, String msg) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, "CMSAdminServlet: " + msg); + } + + /** + * Signed Audit Log Public Key + * + * This method is called to obtain the public key from the passed in + * "KeyPair" object for a signed audit log message. + * <P> + * + * @param object a Key Pair Object + * @return key string containing the public key + */ + private String auditPublicKey(KeyPair object) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + if (object == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + byte rawData[] = null; + + rawData = object.getPublic().getEncoded(); + + String key = null; + StringBuffer sb = new StringBuffer(); + + // convert "rawData" into "base64Data" + if (rawData != null) { + String base64Data = null; + + base64Data = Utils.base64encode(rawData).trim(); + + // extract all line separators from the "base64Data" + for (int i = 0; i < base64Data.length(); i++) { + if (base64Data.substring(i, i).getBytes() != EOL) { + sb.append(base64Data.substring(i, i)); + } + } + } + key = sb.toString(); + + if (key != null) { + key = key.trim(); + + if (key.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return key; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java new file mode 100644 index 000000000..42ff32ebe --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java @@ -0,0 +1,1007 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.DestDef; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.jobs.EJobsException; +import com.netscape.certsrv.jobs.IJob; +import com.netscape.certsrv.jobs.IJobsScheduler; +import com.netscape.certsrv.jobs.JobPlugin; +import com.netscape.certsrv.logging.ILogger; + +/** + * A class representing an administration servlet for the + * Jobs Scheduler and it's scheduled jobs. + * + * @version $Revision$, $Date$ + */ +public class JobsAdminServlet extends AdminServlet { + /** + * + */ + private static final long serialVersionUID = 561767449283982015L; + // ... remove later + private final static String EDIT = ";edit"; + private final static String VISIBLE = ";visible"; + private final static String ENABLED = ";enabled"; + private final static String DISABLED = ";disabled"; + + private final static String INFO = "JobsAdminServlet"; + private IJobsScheduler mJobsSched = null; + + /** + * Constructs JobsAdminServlet. + */ + public JobsAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mJobsSched = (IJobsScheduler) + CMS.getSubsystem(CMS.SUBSYSTEM_JOBS); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * retrieve extended plugin info such as brief description, type info + * from jobs + */ + private void getExtendedPluginInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + int colon = id.indexOf(':'); + + String implType = id.substring(0, colon); + String implName = id.substring(colon + 1); + + NameValuePairs params = + getExtendedPluginInfo(getLocale(req), implType, implName); + + sendResponse(SUCCESS, null, params, resp); + } + + private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) { + IExtendedPluginInfo ext_info = null; + Object impl = null; + + JobPlugin jp = + (JobPlugin) mJobsSched.getPlugins().get(implName); + + if (jp != null) + impl = getClassByNameAsExtendedPluginInfo(jp.getClassPath()); + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + } + + return nvps; + + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + if (op == null) { + //System.out.println("SRVLT_INVALID_PROTOCOL"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + return; + } + + try { + super.authenticate(req); + } catch (IOException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"), + null, resp); + return; + } + + try { + AUTHZ_RES_NAME = "certServer.job.configuration"; + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_JOBS)) + getSettings(req, resp); + else if (scope.equals(ScopeDef.SC_JOBS_IMPLS)) + getConfig(req, resp); + else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE)) + getInstConfig(req, resp); + else if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) { + try { + getExtendedPluginInfo(req, resp); + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + } else { + //System.out.println("SRVLT_INVALID_OP_SCOPE"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_JOBS)) { + setSettings(req, resp); + } else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE)) { + modJobsInst(req, resp, scope); + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_JOBS_IMPLS)) + listJobPlugins(req, resp); + else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE)) + listJobsInsts(req, resp); + else { + //System.out.println("SRVLT_INVALID_OP_SCOPE"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_ADD)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_JOBS_IMPLS)) + addJobPlugin(req, resp, scope); + else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE)) + addJobsInst(req, resp, scope); + else { + //System.out.println("SRVLT_INVALID_OP_SCOPE"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_JOBS_IMPLS)) + delJobPlugin(req, resp, scope); + else if (scope.equals(ScopeDef.SC_JOBS_INSTANCE)) + delJobsInst(req, resp, scope); + else { + //System.out.println("SRVLT_INVALID_OP_SCOPE"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op), + null, resp); + return; + } + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + } + + private synchronized void addJobPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + // is the job plugin id unique? + if (mJobsSched.getPlugins().containsKey((Object) id)) { + sendResponse(ERROR, + new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_JOB_PLUGIN_ID", id)) + .toString(), + null, resp); + return; + } + + String classPath = req.getParameter(Constants.PR_JOBS_CLASS); + + if (classPath == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_NULL_CLASS"), + null, resp); + return; + } + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + // Does the class exist? + Class<?> newImpl = null; + + try { + newImpl = Class.forName(classPath); + } catch (ClassNotFoundException e) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_NO_CLASS"), + null, resp); + return; + } catch (IllegalArgumentException e) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_NO_CLASS"), + null, resp); + return; + } + + // is the class an IJob? + try { + if (IJob.class.isAssignableFrom(newImpl) == false) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_CLASS"), + null, resp); + return; + } + } catch (NullPointerException e) { // unlikely, only if newImpl null. + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_CLASS"), + null, resp); + return; + } + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(Constants.PR_JOBS_CLASS, classPath); + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // add manager to registry. + JobPlugin plugin = new JobPlugin(id, classPath); + + mJobsSched.getPlugins().put(id, plugin); + mJobsSched.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_JS_PLUGIN_ADD", id)); + + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void addJobsInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // is the job instance id unique? + if (mJobsSched.getInstances().containsKey((Object) id)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_JOB_INST_ID"), + null, resp); + return; + } + + // get required parameters + // SC_JOBS_IMPL_NAME is absolutely required, the rest depend on + // on each job plugin + String implname = req.getParameter(Constants.PR_JOBS_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ADD_MISSING_PARAMS"), + null, resp); + return; + } + + // check if implementation exists. + JobPlugin plugin = + (JobPlugin) mJobsSched.getPlugins().get(implname); + + if (plugin == null) { + sendResponse(ERROR, + new + EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_PLUGIN_NOT_FOUND", + id)).toString(), + null, resp); + return; + } + + // now the rest of config parameters + // note that we only check to see if the required parameters + // are there, but not checking the values are valid + String[] configParams = mJobsSched.getConfigParams(implname); + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + IConfigStore substore = instancesConfig.makeSubStore(id); + + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + String key = configParams[i]; + String val = req.getParameter(key); + + if (val != null && !val.equals("")) { + substore.put(key, val); + } else if (!key.equals("profileId")) { + sendResponse(ERROR, + new + EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_MISSING_INST_PARAM_VAL", + key)).toString(), + null, resp); + return; + } + } + } + + substore.put(IJobsScheduler.PROP_PLUGIN, implname); + + // Instantiate an object for this implementation + String className = plugin.getClassPath(); + IJob jobsInst = null; + + try { + jobsInst = (IJob) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new EJobsException( + CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(), + null, resp); + return; + } catch (InstantiationException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new EJobsException( + CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new EJobsException( + CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(), + null, resp); + return; + } + + IJobsScheduler scheduler = (IJobsScheduler) + CMS.getSubsystem(CMS.SUBSYSTEM_JOBS); + + // initialize the job plugin + try { + jobsInst.init(scheduler, id, implname, substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // inited and commited ok. now add manager instance to list. + mJobsSched.getInstances().put(id, jobsInst); + + mJobsSched.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_JOB_INST_ADD", id)); + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_JOBS_IMPL_NAME, implname); + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void listJobPlugins(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mJobsSched.getPlugins().keys(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + JobPlugin value = mJobsSched.getPlugins().get(name); + + params.put(name, value.getClassPath()); + // params.add(name, value.getClassPath()+EDIT); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void listJobsInsts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + for (Enumeration<String> e = mJobsSched.getInstances().keys(); e.hasMoreElements();) { + String name = e.nextElement(); + IJob value = mJobsSched.getInstances().get((Object) name); + + // params.add(name, value.getImplName()); + params.put(name, value.getImplName() + VISIBLE + + (value.isEnabled() ? ENABLED : DISABLED) + ); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void delJobPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does this job plugin exist? + if (mJobsSched.getPlugins().containsKey(id) == false) { + sendResponse(ERROR, + new + EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_PLUGIN_NOT_FOUND", + id)).toString(), + null, resp); + return; + } + + // first check if any instances from this job plugin + // DON'T remove job plugin if any instance + for (Enumeration<IJob> e = mJobsSched.getInstances().elements(); e.hasMoreElements();) { + IJob jobs = e.nextElement(); + + if ((jobs.getImplName()).equals(id)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_IN_USE"), + null, resp); + return; + } + } + + // then delete this job plugin + mJobsSched.getPlugins().remove((Object) id); + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void delJobsInst(HttpServletRequest req, + HttpServletResponse resp, String scope) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does job plugin instance exist? + if (mJobsSched.getInstances().containsKey(id) == false) { + sendResponse(ERROR, + new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_NOT_FOUND", + id)).toString(), + null, resp); + return; + } + + // only remove from memory + // cannot shutdown because we don't keep track of whether it's + // being used. + mJobsSched.getInstances().remove(id); + + // remove the configuration. + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * used for getting the required configuration parameters (with + * possible default values) for a particular job plugin + * implementation name specified in the RS_ID. Actually, there is + * no logic in here to set any default value here...there's no + * default value for any parameter in this job scheduler subsystem + * at this point. Later, if we do have one (or some), it can be + * added. The interface remains the same. + */ + private synchronized void getConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + + String implname = req.getParameter(Constants.RS_ID); + + if (implname == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + String[] configParams = mJobsSched.getConfigParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.put(Constants.PR_JOBS_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + params.put(configParams[i], ""); + } + } + sendResponse(0, null, params, resp); + return; + } + + private synchronized void getInstConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does job plugin instance exist? + if (mJobsSched.getInstances().containsKey(id) == false) { + sendResponse(ERROR, + new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_NOT_FOUND", + id)).toString(), + null, resp); + return; + } + + IJob jobInst = (IJob) mJobsSched.getInstances().get(id); + IConfigStore config = jobInst.getConfigStore(); + String[] configParams = jobInst.getConfigParams(); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_JOBS_IMPL_NAME, jobInst.getImplName()); + + // implName is always required so always send it. + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + String key = configParams[i]; + + String val = (String) config.get(key); + + if (val != null && !val.equals("")) { + params.put(key, val); + } else { + params.put(key, ""); + } + } + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * Modify job plugin instance. + * This will actually create a new instance with new configuration + * parameters and replace the old instance, if the new instance + * created and initialized successfully. + * The old instance is left running. so this is very expensive. + * Restart of server recommended. + */ + private synchronized void modJobsInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + // expensive operation. + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // Does the job instance exist? + if (!mJobsSched.getInstances().containsKey((Object) id)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ILL_JOB_INST_ID"), + null, resp); + return; + } + + // get new implementation (same or different.) + String implname = req.getParameter(Constants.PR_JOBS_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_ADD_MISSING_PARAMS"), + null, resp); + return; + } + + // get plugin for implementation + JobPlugin plugin = + (JobPlugin) mJobsSched.getPlugins().get(implname); + + if (plugin == null) { + sendResponse(ERROR, + new EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_JOB_PLUGIN_NOT_FOUND", + id)).toString(), + null, resp); + return; + } + + // save old instance substore params in case new one fails. + + IJob oldinst = + (IJob) mJobsSched.getInstances().get((Object) id); + IConfigStore oldConfig = oldinst.getConfigStore(); + + String[] oldConfigParms = oldinst.getConfigParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.put(IJobsScheduler.PROP_PLUGIN, + (String) oldConfig.get(IJobsScheduler.PROP_PLUGIN)); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.length; i++) { + String key = oldConfigParms[i]; + Object val = oldConfig.get(key); + + if (val != null) { + saveParams.put(key, (String) val); + } + } + } + + // on to the new instance. + + // remove old substore. + + IConfigStore destStore = + mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN); + IConfigStore instancesConfig = + destStore.getSubStore(scope); + + instancesConfig.removeSubStore(id); + + // create new substore. + + String[] configParams = mJobsSched.getConfigParams(implname); + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(IJobsScheduler.PROP_PLUGIN, implname); + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + String key = configParams[i]; + String val = req.getParameter(key); + + if (val != null && !val.equals("")) { + substore.put(key, val); + } else if (!key.equals("profileId")) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new + EJobsException(CMS.getUserMessage(getLocale(req), "CMS_JOB_SRVLT_MISSING_INST_PARAM_VAL", + key)).toString(), + null, resp); + return; + } + } + } + // Instantiate an object for new implementation + + String className = plugin.getClassPath(); + IJob newJobInst = null; + + try { + newJobInst = (IJob) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new EJobsException( + CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(), + null, resp); + return; + } catch (InstantiationException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new EJobsException( + CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new EJobsException( + CMS.getUserMessage(getLocale(req), "CMS_JOB_LOAD_CLASS_FAILED", className)).toString(), + null, resp); + return; + } + + // initialize the job plugin + + IJobsScheduler scheduler = (IJobsScheduler) + CMS.getSubsystem(CMS.SUBSYSTEM_JOBS); + + try { + newJobInst.init(scheduler, id, implname, substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } catch (Exception e) { + CMS.debug("JobsAdminServlet: modJobsInst: " + e); + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, "unidentified error" + e, null, resp); + return; + } + + // initialized ok. commiting + try { + mConfig.commit(true); + + } catch (EBaseException e) { + // clean up. + restore(instancesConfig, id, saveParams); + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // commited ok. replace instance. + + mJobsSched.getInstances().put(id, newJobInst); + + mJobsSched.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_JOB_INST_REP", id)); + + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private void getSettings(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + IConfigStore config = mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN); + + params.put(Constants.PR_ENABLE, + config.getString(IJobsScheduler.PROP_ENABLED, + Constants.FALSE)); + // default 1 minute + params.put(Constants.PR_JOBS_FREQUENCY, + config.getString(IJobsScheduler.PROP_INTERVAL, "1")); + + //System.out.println("Send: "+params.toString()); + sendResponse(SUCCESS, null, params, resp); + } + + private void setSettings(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + //Save New Settings to the config file + IConfigStore config = mConfig.getSubStore(DestDef.DEST_JOBS_ADMIN); + + String enabled = config.getString(IJobsScheduler.PROP_ENABLED); + String enabledSetTo = req.getParameter(Constants.PR_ENABLE); + boolean enabledChanged = false; + + if (!enabled.equalsIgnoreCase(enabledSetTo)) { + enabledChanged = true; + // set enable flag + config.putString(IJobsScheduler.PROP_ENABLED, enabledSetTo); + } + + //set frequency + String interval = + req.getParameter(Constants.PR_JOBS_FREQUENCY); + + if (interval != null) { + config.putString(IJobsScheduler.PROP_INTERVAL, interval); + mJobsSched.setInterval( + config.getInteger(IJobsScheduler.PROP_INTERVAL)); + } + + if (enabledChanged == true) { + if (enabled.equalsIgnoreCase("false")) { // turned on + mJobsSched.startDaemon(); + } + } + mConfig.commit(true); + + sendResponse(SUCCESS, null, null, resp); + } + + // convenience routine. + private static void restore(IConfigStore store, + String id, NameValuePairs saveParams) { + store.removeSubStore(id); + IConfigStore rstore = store.makeSubStore(id); + + for (String key : saveParams.keySet()) { + String value = saveParams.get(key); + + if (!value.equals("")) + rstore.put(key, value); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java new file mode 100644 index 000000000..eaa5a95c4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java @@ -0,0 +1,234 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; + +/** + * A class representings an administration servlet for Key + * Recovery Authority. This servlet is responsible to serve + * KRA administrative operation such as configuration + * parameter updates. + * + * @version $Revision$, $Date$ + */ +public class KRAAdminServlet extends AdminServlet { + /** + * + */ + private static final long serialVersionUID = -5794220348195666729L; + + protected static final String PROP_ENABLED = "enabled"; + + private final static String INFO = "KRAAdminServlet"; + + private IKeyRecoveryAuthority mKRA = null; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_DRM = + "LOGGING_SIGNED_AUDIT_CONFIG_DRM_3"; + + /** + * Constructs KRA servlet. + */ + public KRAAdminServlet() { + super(); + } + + public void init(ServletConfig config) throws ServletException { + super.init(config); + mKRA = (IKeyRecoveryAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + } + + /** + * Returns serlvet information. + * + * @return name of this servlet + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP admin request. + * + * @param req HTTP request + * @param resp HTTP response + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + super.authenticate(req); + String scope = req.getParameter(Constants.OP_SCOPE); + + if (scope == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + String op = req.getParameter(Constants.OP_TYPE); + + if (op == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op), + null, resp); + return; + } + + try { + AUTHZ_RES_NAME = "certServer.kra.configuration"; + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + /* Functions not implemented in console + if (scope.equals(ScopeDef.SC_AUTO_RECOVERY)) { + readAutoRecoveryConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_RECOVERY)) { + readRecoveryConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) { + getNotificationRIQConfig(req, resp); + return; + } else + */ + if (scope.equals(ScopeDef.SC_GENERAL)) { + getGeneralConfig(req, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + /* Functions not implemented in console + if (scope.equals(ScopeDef.SC_AUTO_RECOVERY)) { + modifyAutoRecoveryConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_AGENT_PWD)) { + changeAgentPwd(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_MNSCHEME)) { + changeMNScheme(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) { + setNotificationRIQConfig(req, resp); + return; + } else + */ + if (scope.equals(ScopeDef.SC_GENERAL)) { + setGeneralConfig(req, resp); + } + } + } catch (EBaseException e) { + // convert exception into locale-specific message + sendResponse(ERROR, e.toString(getLocale(req)), + null, resp); + return; + } catch (Exception e) { + e.printStackTrace(); + } + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + } + + private void getGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + int value = 1; + + value = mKRA.getNoOfRequiredAgents(); + params.put(Constants.PR_NO_OF_REQUIRED_RECOVERY_AGENTS, Integer.toString(value)); + + sendResponse(SUCCESS, null, params, resp); + } + + private void setGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + boolean restart = false; + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_NO_OF_REQUIRED_RECOVERY_AGENTS)) { + try { + int number = Integer.parseInt(value); + mKRA.setNoOfRequiredAgents(number); + } catch (NumberFormatException e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + throw new EBaseException("Number of agents must be an integer"); + } + } + } + + commit(true); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + if (restart) + sendResponse(RESTART, null, null, resp); + else + sendResponse(SUCCESS, null, null, resp); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/LogAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/LogAdminServlet.java new file mode 100644 index 000000000..1b32018bc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/LogAdminServlet.java @@ -0,0 +1,2361 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.logging.ELogException; +import com.netscape.certsrv.logging.ELogNotFound; +import com.netscape.certsrv.logging.ELogPluginNotFound; +import com.netscape.certsrv.logging.ILogEventListener; +import com.netscape.certsrv.logging.ILogSubsystem; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.LogPlugin; + +/** + * A class representings an administration servlet for logging + * subsystem. This servlet is responsible to serve + * logging administrative operation such as configuration + * parameter updates and log retriever. + * + * @version $Revision$, $Date$ + */ +public class LogAdminServlet extends AdminServlet { + + /** + * + */ + private static final long serialVersionUID = -99699953656847603L; + + private final static String INFO = "LogAdminServlet"; + + private ILogSubsystem mSys = null; + + private final static String VIEW = ";" + Constants.VIEW; + private final static String EDIT = ";" + Constants.EDIT; + + private final static String SIGNED_AUDIT_LOG_TYPE = "SignedAudit"; + private final static String LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT = + "LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT_3"; + private final static String LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE = + "LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE_4"; + private final static String LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE = + "LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE_4"; + + /** + * Constructs Log servlet. + */ + public LogAdminServlet() { + super(); + } + + public static Hashtable<String, String> toHashtable(HttpServletRequest req) { + Hashtable<String, String> httpReqHash = new Hashtable<String, String>(); + Enumeration<?> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + httpReqHash.put(name, req.getParameter(name)); + } + return httpReqHash; + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mSys = (ILogSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_LOG); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + String op = req.getParameter(Constants.OP_TYPE); + + if (op == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + return; + } + + super.authenticate(req); + + try { + // perform operation based on scope + String scope = req.getParameter(Constants.OP_SCOPE); + + if (scope != null) { + AUTHZ_RES_NAME = "certServer.log.configuration"; + if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + try { + getExtendedPluginInfo(req, resp); + return; + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + } + + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + + if (scope.equals(ScopeDef.SC_LOG_IMPLS)) { + getConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_LOG_RULES)) { + getInstConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_GENERAL)) { + getGeneralConfig(req, resp); + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + + if (scope.equals(ScopeDef.SC_LOG_IMPLS)) { + delLogPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_LOG_RULES)) { + delLogInst(req, resp, scope); + return; + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_ADD)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + + if (scope.equals(ScopeDef.SC_LOG_IMPLS)) { + addLogPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_LOG_RULES)) { + addLogInst(req, resp, scope); + return; + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + AUTHZ_RES_NAME = "certServer.log.configuration"; + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + + if (scope.equals(ScopeDef.SC_LOG_RULES)) { + modLogInst(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_GENERAL)) { + setGeneralConfig(req, resp); + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_LOG_IMPLS)) { + listLogPlugins(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_LOG_RULES)) { + listLogInsts(req, resp, true); + return; + } else if (scope.equals(ScopeDef.SC_LOG_INSTANCES)) { + listLogInsts(req, resp, false); + return; + } else if (scope.equals(ScopeDef.SC_LOG_CONTENT)) { + String instName = req.getParameter(Constants.PR_LOG_INSTANCE); + + if (instName.equals("System")) { + AUTHZ_RES_NAME = "certServer.log.content.system"; + } else if (instName.equals("Transactions")) { + AUTHZ_RES_NAME = "certServer.log.content.transactions"; + } else if (instName.equals(Constants.PR_LOG_SIGNED_AUDIT)) { + AUTHZ_RES_NAME = "certServer.log.content.signedAudit"; + } + + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + + ILogEventListener loginst = + mSys.getLogInstance(instName); + + if (loginst != null) { + NameValuePairs nvps = loginst.retrieveLogContent(toHashtable(req)); + + sendResponse(SUCCESS, null, nvps, resp); + } + return; + } else if (scope.equals(ScopeDef.SC_LOG_ARCH)) { + String instName = req.getParameter(Constants.PR_LOG_INSTANCE); + + if (instName.equals("System")) { + AUTHZ_RES_NAME = "certServer.log.content.system"; + } else if (instName.equals("Transactions")) { + AUTHZ_RES_NAME = "certServer.log.content.transactions"; + } else if (instName.equals(Constants.PR_LOG_SIGNED_AUDIT)) { + AUTHZ_RES_NAME = "certServer.log.content.signedAudit"; + } + + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + ILogEventListener loginst = + mSys.getLogInstance(instName); + + if (loginst != null) { + NameValuePairs nvps = loginst.retrieveLogList(toHashtable(req)); + + sendResponse(SUCCESS, null, nvps, resp); + } + return; + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op), + null, resp); + return; + } + } + } catch (EBaseException e) { + // if it is EBaseException, we can output better + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + } catch (Exception e) { + System.out.println("XXX >>>" + e.toString() + "<<<"); + e.printStackTrace(); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + } + + return; + } + + private synchronized void listLogInsts(HttpServletRequest req, + HttpServletResponse resp, boolean all) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mSys.getLogInsts().keys(); + + for (; e.hasMoreElements();) { + String name = (String) e.nextElement(); + ILogEventListener value = ((ILogSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_LOG)).getLogInstance(name); + + if (value == null) + continue; + String pName = mSys.getLogPluginName(value); + LogPlugin pClass = (LogPlugin) + mSys.getLogPlugins().get(pName); + String c = pClass.getClassPath(); + + // not show ntEventlog here + if (all || (!all && !c.endsWith("NTEventLog"))) + params.put(name, pName + ";visible"); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * retrieve extended plugin info such as brief description, type info + * from logging + */ + private void getExtendedPluginInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + int colon = id.indexOf(':'); + + String implType = id.substring(0, colon); + String implName = id.substring(colon + 1); + NameValuePairs params = getExtendedPluginInfo(getLocale(req), implType, implName); + + sendResponse(SUCCESS, null, params, resp); + } + + private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) { + IExtendedPluginInfo ext_info = null; + Object impl = null; + LogPlugin lp = (LogPlugin) mSys.getLogPlugins().get(implName); + + if (lp != null) { + impl = getClassByNameAsExtendedPluginInfo(lp.getClassPath()); + } + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + } + + return nvps; + + } + + /** + * Add log plug-in + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of the log's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + @SuppressWarnings("unchecked") + private synchronized void addLogPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String logType = null; + String id = req.getParameter(Constants.RS_ID); + + // if this "required" parameter is not present, + // always log messages to the signed audit log + logType = id; + if (logType == null) { + logType = SIGNED_AUDIT_LOG_TYPE; + } + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // is the log id unique? + if (mSys.getLogPlugins().containsKey((Object) id)) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_PLUGIN_ID", id)) + .toString(), + null, resp); + return; + } + + String classPath = req.getParameter(Constants.PR_LOG_CLASS); + + if (classPath == null) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_NULL_CLASS"), + null, resp); + return; + } + + IConfigStore destStore = null; + + destStore = mConfig.getSubStore("log"); + IConfigStore instancesConfig = + destStore.getSubStore("impl"); + + // Does the class exist? + Class<ILogEventListener> newImpl = null; + + try { + newImpl = (Class<ILogEventListener>) Class.forName(classPath); + } catch (ClassNotFoundException e) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_NO_CLASS"), + null, resp); + return; + } catch (IllegalArgumentException e) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_NO_CLASS"), + null, resp); + return; + } + + // is the class an ILogEventListner? + try { + if (ILogEventListener.class.isAssignableFrom(newImpl) == false) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_CLASS"), + null, resp); + return; + } + } catch (NullPointerException e) { // unlikely, only if newImpl null. + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_CLASS"), + null, resp); + return; + } + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(Constants.PR_LOG_CLASS, classPath); + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // add log to registry. + LogPlugin plugin = new LogPlugin(id, classPath); + + mSys.getLogPlugins().put(id, plugin); + + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private boolean isValidID(String id) { + if (id == null) + return false; + for (int i = 0; i < id.length(); i++) { + if (!Character.isLetterOrDigit(id.charAt(i))) + return false; + } + return true; + } + + /** + * Add log instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of the log's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void addLogInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String logType = null; + String id = req.getParameter(Constants.RS_ID); + + // if this "required" parameter is not present, + // always log messages to the signed audit log + logType = id; + if (logType == null) { + logType = SIGNED_AUDIT_LOG_TYPE; + } + + if (id == null) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + if (!isValidID(id)) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, "Invalid ID '" + id + "'", + null, resp); + return; + } + + if (mSys.getLogInsts().containsKey((Object) id)) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_INST_ID"), + null, resp); + return; + } + + // get required parameters + String implname = req.getParameter( + Constants.PR_LOG_IMPL_NAME); + + if (implname == null) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ADD_MISSING_PARAMS"), + null, resp); + return; + } + + // check if implementation exists. + LogPlugin plugin = + (LogPlugin) mSys.getLogPlugins().get( + implname); + + if (plugin == null) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse( + ERROR, + new ELogPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_PLUGIN_NOT_FOUND", implname)) + .toString(), + null, resp); + return; + } + + Vector<String> configParams = mSys.getLogDefaultParams(implname); + + IConfigStore destStore = + mConfig.getSubStore("log"); + IConfigStore instancesConfig = + destStore.getSubStore("instance"); + IConfigStore substore = instancesConfig.makeSubStore(id); + + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + String val = req.getParameter(kv.substring(0, index)); + + if (val == null) { + substore.put(kv.substring(0, index), + kv.substring(index + 1)); + } else { + substore.put(kv.substring(0, index), + val); + } + } + } + substore.put("pluginName", implname); + + // Fix Blackflag Bug #615603: Currently, although expiring log + // files is no longer supported, it is still a required parameter + // that must be present during the creation and modification of + // custom log plugins. + substore.put("expirationTime", "0"); + + // Instantiate an object for this implementation + String className = plugin.getClassPath(); + ILogEventListener logInst = null; + + try { + logInst = (ILogEventListener) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + instancesConfig.removeSubStore(id); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + instancesConfig.removeSubStore(id); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + instancesConfig.removeSubStore(id); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className)) + .toString(), + null, resp); + return; + } + + // initialize the log + try { + logInst.init(mSys, substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + instancesConfig.removeSubStore(id); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } catch (Throwable e) { + instancesConfig.removeSubStore(id); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, e.toString(), null, resp); + return; + } + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + instancesConfig.removeSubStore(id); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // inited and commited ok. now add log instance to list. + mSys.getLogInsts().put(id, logInst); + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_LOG_IMPL_NAME, implname); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private synchronized void listLogPlugins(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mSys.getLogPlugins().keys(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + LogPlugin value = (LogPlugin) + mSys.getLogPlugins().get(name); + // get Description + String c = value.getClassPath(); + String desc = "unknown"; + + try { + ILogEventListener lp = (ILogEventListener) + Class.forName(c).newInstance(); + + desc = lp.getDescription(); + } catch (Exception exp) { + sendResponse(ERROR, exp.toString(), null, + resp); + return; + } + params.put(name, value.getClassPath() + "," + desc); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + public String getLogPluginName(ILogEventListener log) { + IConfigStore cs = log.getConfigStore(); + + try { + return cs.getString("pluginName", ""); + } catch (EBaseException e) { + return ""; + } + } + + /** + * Delete log instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of the log's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void delLogInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String logType = null; + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + // if this "required" parameter is not present, + // always log messages to the signed audit log + logType = id; + if (logType == null) { + logType = SIGNED_AUDIT_LOG_TYPE; + } + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // Does the log instance exist? + if (mSys.getLogInsts().containsKey(id) == false) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_INSTANCE_NOT_FOUND", id)) + .toString(), + null, resp); + return; + } + + // only remove from memory + // cannot shutdown because we don't keep track of whether it's + // being used. + mSys.getLogInsts().remove(id); + + // remove the configuration. + IConfigStore destStore = + mConfig.getSubStore("log"); + IConfigStore instancesConfig = + destStore.getSubStore("instance"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Delete log plug-in + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of the log's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void delLogPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String logType = null; + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + // if this "required" parameter is not present, + // always log messages to the signed audit log + logType = id; + if (logType == null) { + logType = SIGNED_AUDIT_LOG_TYPE; + } + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + if (mSys.getLogPlugins().containsKey(id) == false) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_PLUGIN_NOT_FOUND", id)) + .toString(), + null, resp); + return; + } + + // first check if any instances from this log + // DON'T remove log if any instance + for (Enumeration<String> e = mSys.getLogInsts().keys(); e.hasMoreElements();) { + String name = (String) e.nextElement(); + ILogEventListener log = mSys.getLogInstance(name); + + if (getLogPluginName(log) == id) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_IN_USE"), + null, resp); + return; + } + } + + // then delete this log + mSys.getLogPlugins().remove((Object) id); + + IConfigStore destStore = + mConfig.getSubStore("log"); + IConfigStore instancesConfig = + destStore.getSubStore("impl"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(SUCCESS, null, params, resp); + return; + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Modify log instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT used when configuring signedAudit + * <li>signed.audit LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE used when log file name (including any path changes) for + * any of audit, system, transaction, or other customized log file change is attempted (authorization should not + * allow, but make sure it's written after the attempt) + * <li>signed.audit LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE used when log expiration time change is attempted + * (authorization should not allow, but make sure it's written after the attempt) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param scope string used to obtain the contents of the log's substore + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void modLogInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String logType = null; + String origLogPath = req.getParameter(Constants.PR_LOG_FILENAME); + String newLogPath = origLogPath; + String origExpirationTime = req.getParameter( + Constants.PR_LOG_EXPIRED_TIME); + String newExpirationTime = origExpirationTime; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + // if this "required" parameter is not present, + // always log messages to the signed audit log + logType = id; + if (logType == null) { + logType = SIGNED_AUDIT_LOG_TYPE; + } + + if (origLogPath != null) { + origLogPath = origLogPath.trim(); + newLogPath = newLogPath.trim(); + } else { + origLogPath = ""; + newLogPath = ""; + } + + if (origExpirationTime != null) { + origExpirationTime = origExpirationTime.trim(); + newExpirationTime = newExpirationTime.trim(); + } else { + origExpirationTime = ""; + newExpirationTime = ""; + } + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // Does the manager instance exist? + if (!mSys.getLogInsts().containsKey((Object) id)) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ILL_INST_ID"), + null, resp); + return; + } + + // get new implementation (same or different.) + String implname = req.getParameter(Constants.PR_LOG_IMPL_NAME); + + if (implname == null) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_LOG_SRVLT_ADD_MISSING_PARAMS"), + + null, resp); + return; + } + // get plugin for implementation + LogPlugin plugin = + (LogPlugin) mSys.getLogPlugins().get(implname); + + if (plugin == null) { + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse( + ERROR, + new ELogPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_PLUGIN_NOT_FOUND", implname)) + .toString(), null, resp); + return; + } + + // save old instance substore params in case new one fails. + + ILogEventListener oldinst = + (ILogEventListener) mSys.getLogInstance(id); + Vector<String> oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.put("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = (String) oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + + saveParams.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + // on to the new instance. + + // remove old substore. + + IConfigStore destStore = + mConfig.getSubStore("log"); + IConfigStore instancesConfig = + destStore.getSubStore("instance"); + + // create new substore. + + Vector<String> configParams = mSys.getLogInstanceParams(id); + + //instancesConfig.removeSubStore(id); + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put("pluginName", implname); + + // Fix Blackflag Bug #615603: Currently, although expiring log + // files is no longer supported, it is still a required parameter + // that must be present during the creation and modification of + // custom log plugins. + substore.put("expirationTime", "0"); + + // IMPORTANT: save a copy of the original log file path + origLogPath = substore.getString(Constants.PR_LOG_FILENAME); + newLogPath = origLogPath; + + if (origLogPath != null) { + origLogPath = origLogPath.trim(); + newLogPath = newLogPath.trim(); + } else { + origLogPath = ""; + newLogPath = ""; + } + + // IMPORTANT: save a copy of the original log expiration time + origExpirationTime = substore.getString( + Constants.PR_LOG_EXPIRED_TIME); + newExpirationTime = origExpirationTime; + + if (origExpirationTime != null) { + origExpirationTime = origExpirationTime.trim(); + newExpirationTime = newExpirationTime.trim(); + } else { + origExpirationTime = ""; + newExpirationTime = ""; + } + + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + AUTHZ_RES_NAME = + "certServer.log.configuration"; + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + String key = kv.substring(0, index); + String val = req.getParameter(key); + + if (key.equals("level")) { + if (val.equals(ILogger.LL_DEBUG_STRING)) + val = "0"; + else if (val.equals(ILogger.LL_INFO_STRING)) + val = "1"; + else if (val.equals(ILogger.LL_WARN_STRING)) + val = "2"; + else if (val.equals(ILogger.LL_FAILURE_STRING)) + val = "3"; + else if (val.equals(ILogger.LL_MISCONF_STRING)) + val = "4"; + else if (val.equals(ILogger.LL_CATASTRPHE_STRING)) + val = "5"; + else if (val.equals(ILogger.LL_SECURITY_STRING)) + val = "6"; + + } + + if (key.equals("rolloverInterval")) { + if (val.equals("Hourly")) + val = Integer.toString(60 * 60); + else if (val.equals("Daily")) + val = Integer.toString(60 * 60 * 24); + else if (val.equals("Weekly")) + val = Integer.toString(60 * 60 * 24 * 7); + else if (val.equals("Monthly")) + val = Integer.toString(60 * 60 * 24 * 30); + else if (val.equals("Yearly")) + val = Integer.toString(60 * 60 * 24 * 365); + } + + if (val != null) { + if (key.equals("fileName")) { + String origVal = substore.getString(key); + + val = val.trim(); + newLogPath = val; + if (!val.equals(origVal.trim())) { + AUTHZ_RES_NAME = + "certServer.log.configuration.fileName"; + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + // store a message in the signed audit log + // file (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log + // file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + } + } + /* + if (key.equals("expirationTime")) { + String origVal = substore.getString(key); + + val = val.trim(); + newExpirationTime = val; + if (!val.equals(origVal.trim())) { + if (id.equals(SIGNED_AUDIT_LOG_TYPE)) { + AUTHZ_RES_NAME = + "certServer.log.configuration.signedAudit.expirationTime"; + } + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + // store a message in the signed audit log + // file (regardless of logType) + if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newExpirationTime); + + audit(auditMessage); + } + + // store a message in the signed audit log + // file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + } + } + */ + substore.put(key, val); + } + } + } + + // Instantiate an object for new implementation + + String className = plugin.getClassPath(); + @SuppressWarnings("unused") + ILogEventListener newMgrInst = null; + + try { + newMgrInst = (ILogEventListener) + Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // check to see if the log file path parameter was changed + newLogPath = auditCheckLogPath(req); + + // check to see if the log expiration time parameter was changed + // newExpirationTime = auditCheckLogExpirationTime(req); + + // cleanup + restore(instancesConfig, id, saveParams); + + // store a message in the signed audit log file + // (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log file + // (regardless of logType) + /* + if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newExpirationTime); + + audit(auditMessage); + }*/ + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + // check to see if the log file path parameter was changed + newLogPath = auditCheckLogPath(req); + + // check to see if the log expiration time parameter was changed + //newExpirationTime = auditCheckLogExpirationTime(req); + + restore(instancesConfig, id, saveParams); + + // store a message in the signed audit log file + // (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log file + // (regardless of logType) + /*if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newExpirationTime); + + audit(auditMessage); + }*/ + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + // check to see if the log file path parameter was changed + newLogPath = auditCheckLogPath(req); + + // check to see if the log expiration time parameter was changed + //newExpirationTime = auditCheckLogExpirationTime(req); + + restore(instancesConfig, id, saveParams); + + // store a message in the signed audit log file + // (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log file + // (regardless of logType) + /* if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newExpirationTime); + + audit(auditMessage); + } */ + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + new ELogException(CMS.getUserMessage(getLocale(req), "CMS_LOG_LOAD_CLASS_FAIL", className)) + .toString(), + null, resp); + return; + } + // initialize the log + + // initialized ok. commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // check to see if the log file path parameter was changed + newLogPath = auditCheckLogPath(req); + + // check to see if the log expiration time parameter was changed + // newExpirationTime = auditCheckLogExpirationTime(req); + + // clean up. + restore(instancesConfig, id, saveParams); + //System.out.println("SRVLT_FAIL_COMMIT"); + + // store a message in the signed audit log file + // (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log file + // (regardless of logType) + /* if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newExpirationTime); + + audit(auditMessage); + }*/ + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // commited ok. replace instance. + + // REMOVED - we didn't do anything to shut off the old instance + // so, it will still be running at this point. You'd have two + // log isntances writing to the same file - this would be a big PROBLEM!!! + + //mSys.getLogInsts().put(id, newMgrInst); + + NameValuePairs params = new NameValuePairs(); + + // check to see if the log file path parameter was changed + newLogPath = auditCheckLogPath(req); + + // check to see if the log expiration time parameter was changed + //newExpirationTime = auditCheckLogExpirationTime(req); + + // store a message in the signed audit log file + // (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.SUCCESS, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log file + // (regardless of logType) + /*if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.SUCCESS, + logType, + newExpirationTime); + + audit(auditMessage); + }*/ + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + } + + sendResponse(RESTART, null, params, resp); + return; + } catch (EBaseException eAudit1) { + // check to see if the log file path parameter was changed + newLogPath = auditCheckLogPath(req); + + // check to see if the log expiration time parameter was changed + // newExpirationTime = auditCheckLogExpirationTime(req); + + // store a message in the signed audit log file + // (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log file + // (regardless of logType) + /* if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newExpirationTime); + + audit(auditMessage); + } */ + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // check to see if the log file path parameter was changed + newLogPath = auditCheckLogPath(req); + + // check to see if the log expiration time parameter was changed + // newExpirationTime = auditCheckLogExpirationTime(req); + + // store a message in the signed audit log file + // (regardless of logType) + if (!(newLogPath.equals(origLogPath))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newLogPath); + + audit(auditMessage); + } + + // store a message in the signed audit log file + // (regardless of logType) + /*if (!(newExpirationTime.equals(origExpirationTime))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + auditSubjectID, + ILogger.FAILURE, + logType, + newExpirationTime); + + audit(auditMessage); + }*/ + + // store a message in the signed audit log file + if (logType.equals(SIGNED_AUDIT_LOG_TYPE)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + } + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // check to see if the log file path parameter was changed + // newLogPath = auditCheckLogPath( req ); + // + // // check to see if the log expiration time parameter was changed + // newExpirationTime = auditCheckLogExpirationTime( req ); + // + // // store a message in the signed audit log file + // // (regardless of logType) + // if( !( newLogPath.equals( origLogPath ) ) ) { + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_LOG_PATH_CHANGE, + // auditSubjectID, + // ILogger.FAILURE, + // logType, + // newLogPath ); + // + // audit( auditMessage ); + // } + // + // // store a message in the signed audit log file + // // (regardless of logType) + // if( !( newExpirationTime.equals( origExpirationTime ) ) ) { + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_LOG_EXPIRATION_CHANGE, + // auditSubjectID, + // ILogger.FAILURE, + // logType, + // newExpirationTime ); + // + // audit( auditMessage ); + // } + // + // // store a message in the signed audit log file + // if( logType.equals( SIGNED_AUDIT_LOG_TYPE ) ) { + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_SIGNED_AUDIT, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // } + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * used for getting the required configuration parameters (with + * possible default values) for a particular plugin + * implementation name specified in the RS_ID. Actually, there is + * no logic in here to set any default value here...there's no + * default value for any parameter in this log subsystem + * at this point. Later, if we do have one (or some), it can be + * added. The interface remains the same. + */ + private synchronized void getConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + + String implname = req.getParameter(Constants.RS_ID); + + if (implname == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + Vector<String> configParams = mSys.getLogDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.put(Constants.PR_LOG_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + if (index == -1) { + params.put(kv, ""); + } else { + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + } + sendResponse(0, null, params, resp); + return; + } + + private synchronized void getInstConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does log instance exist? + if (mSys.getLogInsts().containsKey(id) == false) { + sendResponse(ERROR, + new ELogNotFound(CMS.getUserMessage(getLocale(req), "CMS_LOG_INSTANCE_NOT_FOUND", id)).toString(), + null, resp); + return; + } + + ILogEventListener logInst = (ILogEventListener) + mSys.getLogInstance(id); + Vector<String> configParams = logInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_LOG_IMPL_NAME, + getLogPluginName(logInst)); + // implName is always required so always send it. + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + // convenience routine. + private static void restore(IConfigStore store, + String id, NameValuePairs saveParams) { + store.removeSubStore(id); + IConfigStore rstore = store.makeSubStore(id); + + for (String key : saveParams.keySet()) { + String value = saveParams.get(key); + + if (value != null) + rstore.put(key, value); + } + } + + /** + * Signed Audit Check Log Path + * + * This method is called to extract the log file path. + * <P> + * + * @param req http servlet request + * @return a string containing the log file path + */ + private String auditCheckLogPath(HttpServletRequest req) { + // check to see if the log file path parameter was changed + String logPath = req.getParameter(Constants.PR_LOG_FILENAME); + + if (logPath == null) { + logPath = ""; + } + + logPath = logPath.trim(); + + return logPath; + } + + private void getGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + String value = "false"; + + value = mConfig.getString(Constants.PR_DEBUG_LOG_ENABLE, "false"); + params.put(Constants.PR_DEBUG_LOG_ENABLE, value); + + value = mConfig.getString(Constants.PR_DEBUG_LOG_LEVEL, "0"); + params.put(Constants.PR_DEBUG_LOG_LEVEL, value); + + sendResponse(SUCCESS, null, params, resp); + } + + private void setGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + boolean restart = false; + + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_DEBUG_LOG_ENABLE)) { + if (value.equals("true") || value.equals("false")) { + mConfig.putString(Constants.PR_DEBUG_LOG_ENABLE, value); + } else { + CMS.debug("setGeneralConfig: Invalid value for " + Constants.PR_DEBUG_LOG_ENABLE + ": " + value); + throw new EBaseException("Invalid value for " + Constants.PR_DEBUG_LOG_ENABLE); + } + } else if (key.equals(Constants.PR_DEBUG_LOG_LEVEL)) { + try { + Integer.parseInt(value); // check for errors + mConfig.putString(Constants.PR_DEBUG_LOG_LEVEL, value); + } catch (NumberFormatException e) { + CMS.debug("setGeneralConfig: Invalid value for " + Constants.PR_DEBUG_LOG_LEVEL + ": " + value); + throw new EBaseException("Invalid value for " + Constants.PR_DEBUG_LOG_LEVEL); + } + } + } + + mConfig.commit(true); + + if (restart) + sendResponse(RESTART, null, null, resp); + else + sendResponse(SUCCESS, null, null, resp); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java new file mode 100644 index 000000000..0e6784413 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java @@ -0,0 +1,543 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.certsrv.ocsp.IOCSPStore; + +/** + * A class representings an administration servlet for Certificate + * Authority. This servlet is responsible to serve OCSP + * administrative operations such as configuration parameter + * updates. + * + * @version $Revision$, $Date$ + */ +public class OCSPAdminServlet extends AdminServlet { + + /** + * + */ + private static final long serialVersionUID = -3349635369730415767L; + + protected static final String PROP_ENABLED = "enabled"; + + private final static String INFO = "OCSPAdminServlet"; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE = + "LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE_3"; + + private IOCSPAuthority mOCSP = null; + + public OCSPAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mOCSP = (IOCSPAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_OCSP); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP request. Each request is authenticated to + * the authenticate manager. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + //get all operational flags + String op = req.getParameter(Constants.OP_TYPE); + String scope = req.getParameter(Constants.OP_SCOPE); + + //check operational flags + if ((op == null) || (scope == null)) { + sendResponse(1, "Invalid Protocol", null, resp); + return; + } + + super.authenticate(req); + + try { + AUTHZ_RES_NAME = "certServer.ocsp.configuration"; + if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + try { + getExtendedPluginInfo(req, resp); + return; + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + } + } + + if (scope.equals(ScopeDef.SC_OCSPSTORE_DEFAULT)) { + if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + setDefaultStore(req, resp); + return; + } + } + + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GENERAL)) { + getGeneralConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_OCSPSTORES_RULES)) { + getOCSPStoresConfig(req, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GENERAL)) { + setGeneralConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_OCSPSTORES_RULES)) { + setOCSPStoresConfig(req, resp); + return; + } + } else if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_OCSPSTORES_RULES)) { + listOCSPStoresConfig(req, resp); + return; + } + } + } catch (Exception e) { + sendResponse(1, e.toString(), null, resp); + return; + } + } + + /** + * retrieve extended plugin info such as brief description, + * type info from CRL extensions + */ + private void getExtendedPluginInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + int colon = id.indexOf(':'); + + String implType = id.substring(0, colon); + String implName = id.substring(colon + 1); + + NameValuePairs params = + getExtendedPluginInfo(getLocale(req), implType, implName); + + sendResponse(SUCCESS, null, params, resp); + } + + private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) { + IExtendedPluginInfo ext_info = null; + Object impl = null; + + impl = getClassByNameAsExtendedPluginInfo(implName); + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + } + + return nvps; + + } + + /** + * Set default OCSP store + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE used when configuring OCSP profile (everything under + * Online Certificate Status Manager) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void setDefaultStore(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + mOCSP.getConfigStore().putString(IOCSPAuthority.PROP_DEF_STORE_ID, + id); + commit(true); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void getOCSPStoresConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + IOCSPStore store = mOCSP.getOCSPStore(id); + NameValuePairs params = store.getConfigParameters(); + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Set OCSP store configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE used when configuring OCSP profile (everything under + * Online Certificate Status Manager) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void setOCSPStoresConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + NameValuePairs params = new NameValuePairs(); + + String id = req.getParameter(Constants.RS_ID); + + IOCSPStore store = mOCSP.getOCSPStore(id); + + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_CRLEXT_IMPL_NAME)) + continue; + if (name.equals("RULENAME")) + continue; + String value = req.getParameter(name); + + params.put(name, value); + } + store.setConfigParameters(params); + commit(true); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void listOCSPStoresConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + IConfigStore config = mOCSP.getConfigStore(); + String defStore = config.getString(IOCSPAuthority.PROP_DEF_STORE_ID); + IConfigStore SubStore = config.getSubStore(IOCSPAuthority.PROP_STORE); + Enumeration<String> enumStores = SubStore.getSubStoreNames(); + + while (enumStores.hasMoreElements()) { + String storeName = enumStores.nextElement(); + boolean storeEnabled = false; + + if (storeName.equals(defStore)) { + storeEnabled = true; + } + params.put(storeName, storeName + ";visible;" + ((storeEnabled) ? "enabled" : "disabled")); + } + sendResponse(SUCCESS, null, params, resp); + } + + private void getGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + getSigningAlgConfig(params); + + sendResponse(SUCCESS, null, params, resp); + } + + private void getSigningAlgConfig(NameValuePairs params) { + params.put(Constants.PR_DEFAULT_ALGORITHM, + mOCSP.getDefaultAlgorithm()); + String[] algorithms = mOCSP.getOCSPSigningAlgorithms(); + StringBuffer algorStr = new StringBuffer(); + + for (int i = 0; i < algorithms.length; i++) { + if (i == 0) + algorStr.append(algorithms[i]); + else + algorStr.append(":"); + algorStr.append(algorithms[i]); + } + params.put(Constants.PR_ALL_ALGORITHMS, algorStr.toString()); + } + + /** + * Set general OCSP configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE used when configuring OCSP profile (everything under + * Online Certificate Status Manager) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private void setGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_DEFAULT_ALGORITHM)) { + mOCSP.setDefaultAlgorithm(value); + } + } + + commit(true); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_OCSP_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java new file mode 100644 index 000000000..0bcb962ea --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java @@ -0,0 +1,1258 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.IPolicyProcessor; +import com.netscape.certsrv.policy.IPolicyRule; +import com.netscape.certsrv.ra.IRegistrationAuthority; + +/** + * This class is an administration servlet for policy management. + * + * Each service (CA, KRA, RA) should be responsible + * for registering an instance of this with the remote + * administration subsystem. + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class PolicyAdminServlet extends AdminServlet { + /** + * + */ + private static final long serialVersionUID = 8850646362111106656L; + + public final static String PROP_AUTHORITY = "authority"; + + private final static String INFO = "PolicyAdminServlet"; + private final static String PW_PASSWORD_CACHE_ADD = + "PASSWORD_CACHE_ADD"; + + public final static String PROP_PREDICATE = "predicate"; + private IPolicyProcessor mProcessor = null; + private IAuthority mAuthority = null; + + // These will be moved to PolicyResources + public static String INVALID_POLICY_SCOPE = "Invalid policy administration scope"; + public static String INVALID_POLICY_IMPL_OP = "Invalid operation for policy implementation management"; + public static String NYI = "Not Yet Implemented"; + public static String INVALID_POLICY_IMPL_CONFIG = "Invalid policy implementation configuration"; + public static String INVALID_POLICY_INSTANCE_CONFIG = "Invalid policy instance configuration"; + public static String MISSING_POLICY_IMPL_ID = "Missing policy impl id in request"; + public static String MISSING_POLICY_IMPL_CLASS = "Missing policy impl class in request"; + public static String INVALID_POLICY_IMPL_ID = "Invalid policy impl id in request"; + public static String MISSING_POLICY_INST_ID = "Missing policy impl id in request"; + public static String INVALID_POLICY_INST_ID = "Invalid policy impl id in request"; + public static String COMMA = ","; + public static String MISSING_POLICY_ORDERING = "Missing policy ordering"; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY = + "LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY_3"; + + /** + * Constructs administration servlet. + */ + public PolicyAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + String authority = config.getInitParameter(PROP_AUTHORITY); + String policyStatus = null; + + CMS.debug("PolicyAdminServlet: In Policy Admin Servlet init!"); + + // CMS 6.1 began utilizing the "Certificate Profiles" framework + // instead of the legacy "Certificate Policies" framework. + // + // Beginning with CS 8.1, to meet the Common Criteria evaluation + // performed on this version of the product, it was determined + // that this legacy "Certificate Policies" framework would be + // deprecated and disabled by default (see Bugzilla Bug #472597). + // + // NOTE: The "Certificate Policies" framework ONLY applied to + // to CA, KRA, and legacy RA (pre-CMS 7.0) subsystems. + // + // Further, the "PolicyAdminServlet.java" servlet is ONLY used + // by the CA Console for the following: + // + // SERVLET-NAME URL-PATTERN + // ==================================================== + // capolicy ca/capolicy + // + // Finally, the "PolicyAdminServlet.java" servlet is ONLY used + // by the KRA Console for the following: + // + // SERVLET-NAME URL-PATTERN + // ==================================================== + // krapolicy kra/krapolicy + // + if (authority != null) + mAuthority = (IAuthority) CMS.getSubsystem(authority); + if (mAuthority != null) + if (mAuthority instanceof ICertificateAuthority) { + mProcessor = ((ICertificateAuthority) mAuthority).getPolicyProcessor(); + try { + policyStatus = ICertificateAuthority.ID + + "." + "Policy" + + "." + IPolicyProcessor.PROP_ENABLE; + if (mConfig.getBoolean(policyStatus, true) == true) { + // NOTE: If "ca.Policy.enable=<boolean>" is missing, + // then the referenced instance existed prior + // to this name=value pair existing in its + // 'CS.cfg' file, and thus we err on the + // side that the user may still need to + // use the policy framework. + CMS.debug("PolicyAdminServlet::init " + + "Certificate Policy Framework (deprecated) " + + "is ENABLED"); + } else { + // CS 8.1 Default: ca.Policy.enable=false + CMS.debug("PolicyAdminServlet::init " + + "Certificate Policy Framework (deprecated) " + + "is DISABLED"); + return; + } + } catch (EBaseException e) { + throw new ServletException(authority + + " does not have a " + + "master policy switch called '" + + policyStatus + "'"); + } + } else if (mAuthority instanceof IRegistrationAuthority) { + // this refers to the legacy RA (pre-CMS 7.0) + mProcessor = ((IRegistrationAuthority) mAuthority).getPolicyProcessor(); + } else if (mAuthority instanceof IKeyRecoveryAuthority) { + mProcessor = ((IKeyRecoveryAuthority) mAuthority).getPolicyProcessor(); + try { + policyStatus = IKeyRecoveryAuthority.ID + + "." + "Policy" + + "." + IPolicyProcessor.PROP_ENABLE; + if (mConfig.getBoolean(policyStatus, true) == true) { + // NOTE: If "kra.Policy.enable=<boolean>" is missing, + // then the referenced instance existed prior + // to this name=value pair existing in its + // 'CS.cfg' file, and thus we err on the + // side that the user may still need to + // use the policy framework. + CMS.debug("PolicyAdminServlet::init " + + "Certificate Policy Framework (deprecated) " + + "is ENABLED"); + } else { + // CS 8.1 Default: kra.Policy.enable=false + CMS.debug("PolicyAdminServlet::init " + + "Certificate Policy Framework (deprecated) " + + "is DISABLED"); + return; + } + } catch (EBaseException e) { + throw new ServletException(authority + + " does not have a " + + "master policy switch called '" + + policyStatus + "'"); + } + } else + throw new ServletException(authority + " does not have policy processor!"); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * retrieve extended plugin info such as brief description, type info + * from policy, authentication, + * need to add: listener, mapper and publishing plugins + */ + private void getExtendedPluginInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + if (!readAuthorize(req, resp)) + return; + String id = req.getParameter(Constants.RS_ID); + NameValuePairs params = null; + + int colon = id.indexOf(':'); + + String implType = id.substring(0, colon); + String implName1 = id.substring(colon + 1); + String implName = implName1; + String instName = null; + + colon = implName1.indexOf(':'); + if (colon > -1) { + implName = implName1.substring(0, colon); + instName = implName1.substring(colon + 1); + params = getExtendedPluginInfo(getLocale(req), implType, implName, instName); + } else { + params = getExtendedPluginInfo(getLocale(req), implType, implName); + } + sendResponse(SUCCESS, null, params, resp); + } + + private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) { + IExtendedPluginInfo ext_info = null; + Object impl = null; + IPolicyRule policy = mProcessor.getPolicyImpl(implName); + + impl = policy; + + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + } + + return nvps; + } + + public NameValuePairs getExtendedPluginInfo(Locale locale, String pluginType, + String implName, + String instName) { + IExtendedPluginInfo ext_info = null; + + Object impl = null; + + IPolicyRule policy = mProcessor.getPolicyInstance(instName); + + impl = policy; + if (impl == null) { + impl = mProcessor.getPolicyImpl(implName); + } + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + + } + + if (nvps != null) { + addDefaultParams(impl, nvps); + } + + return nvps; + } + + private void addDefaultParams(Object ext_info, NameValuePairs nvps) { + + /* make sure policy rules have 'enable' and 'predicate' */ + + if (ext_info instanceof IPolicyRule) { + if (nvps.get(IPolicyRule.PROP_ENABLE) == null) { + nvps.put(IPolicyRule.PROP_ENABLE, "boolean;Enable this policy rule"); + } + if (nvps.get(PROP_PREDICATE) == null) { + nvps.put(PROP_PREDICATE, "string;Rules describing when this policy should run."); + } + } + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + super.authenticate(req); + + AUTHZ_RES_NAME = "certServer.policy.configuration"; + String scope = req.getParameter(Constants.OP_SCOPE); + + if (scope.equals(ScopeDef.SC_POLICY_RULES)) + processPolicyRuleMgmt(req, resp); + else if (scope.equals(ScopeDef.SC_POLICY_IMPLS)) + processPolicyImplMgmt(req, resp); + else if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) { + try { + getExtendedPluginInfo(req, resp); + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + } else + sendResponse(ERROR, INVALID_POLICY_SCOPE, null, resp); + } + + private boolean readAuthorize(HttpServletRequest req, + HttpServletResponse resp) throws IOException { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return false; + } + return true; + } + + private boolean modifyAuthorize(HttpServletRequest req, + HttpServletResponse resp) throws IOException { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return false; + } + return true; + } + + /** + * Process Policy Implementation Management. + */ + public void processPolicyImplMgmt(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_SEARCH)) { + if (!readAuthorize(req, resp)) + return; + listPolicyImpls(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + if (!modifyAuthorize(req, resp)) + return; + deletePolicyImpl(req, resp); + } else if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getPolicyImplConfig(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addPolicyImpl(req, resp); + } else + sendResponse(ERROR, INVALID_POLICY_IMPL_OP, + null, resp); + } + + public void processPolicyRuleMgmt(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_SEARCH)) { + if (!readAuthorize(req, resp)) + return; + listPolicyInstances(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + if (!modifyAuthorize(req, resp)) + return; + deletePolicyInstance(req, resp); + } else if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getPolicyInstanceConfig(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addPolicyInstance(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + if (!modifyAuthorize(req, resp)) + return; + String id = req.getParameter(Constants.RS_ID); + + if (id.equalsIgnoreCase(Constants.RS_ID_ORDER)) + changePolicyInstanceOrdering(req, resp); + else + modifyPolicyInstance(req, resp); + } else + sendResponse(ERROR, INVALID_POLICY_IMPL_OP, + null, resp); + } + + public void listPolicyImpls(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + Enumeration<String> policyImplNames = mProcessor.getPolicyImplsInfo(); + Enumeration<IPolicyRule> policyImpls = mProcessor.getPolicyImpls(); + + if (policyImplNames == null || + policyImpls == null) { + sendResponse(ERROR, INVALID_POLICY_IMPL_CONFIG, null, resp); + return; + } + + // Assemble a name value pair; + NameValuePairs nvp = new NameValuePairs(); + + while (policyImplNames.hasMoreElements() && + policyImpls.hasMoreElements()) { + String id = policyImplNames.nextElement(); + IPolicyRule impl = policyImpls.nextElement(); + String className = + impl.getClass().getName(); + String desc = impl.getDescription(); + + nvp.put(id, className + "," + desc); + } + sendResponse(SUCCESS, null, nvp, resp); + } + + public void listPolicyInstances(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + Enumeration<String> instancesInfo = mProcessor.getPolicyInstancesInfo(); + + if (instancesInfo == null) { + sendResponse(ERROR, INVALID_POLICY_INSTANCE_CONFIG, null, resp); + return; + } + + // Assemble name value pairs + NameValuePairs nvp = new NameValuePairs(); + + while (instancesInfo.hasMoreElements()) { + String info = instancesInfo.nextElement(); + int i = info.indexOf(";"); + + nvp.put(info.substring(0, i), info.substring(i + 1)); + + } + sendResponse(SUCCESS, null, nvp, resp); + } + + /** + * Delete policy implementation + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and + * extensions + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void deletePolicyImpl(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id. + String id = req.getParameter(Constants.RS_ID).trim(); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + try { + mProcessor.deletePolicyImpl(id); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (Exception e) { + //e.printStackTrace(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, e.toString(), null, resp); + } + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_POLICY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + public void getPolicyImplConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get the policy impl id. + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + Vector<String> v = mProcessor.getPolicyImplConfig(id); + + if (v == null) { + sendResponse(ERROR, INVALID_POLICY_IMPL_ID, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + for (Enumeration<String> e = v.elements(); e.hasMoreElements();) { + String nv = e.nextElement(); + int index = nv.indexOf("="); + + nvp.put(nv.substring(0, index), nv.substring(index + 1)); + } + sendResponse(SUCCESS, null, nvp, resp); + } + + /** + * Add policy implementation + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and + * extensions + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addPolicyImpl(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id and class path. + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + String classPath = req.getParameter(Constants.PR_POLICY_CLASS); + + if (classPath == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_IMPL_CLASS, null, resp); + return; + } + try { + mProcessor.addPolicyImpl(id, classPath); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, e.toString(), null, resp); + } + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_POLICY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Delete policy instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and + * extensions + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void deletePolicyInstance(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id. + String id = req.getParameter(Constants.RS_ID).trim(); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp); + return; + } + + try { + mProcessor.deletePolicyInstance(id); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (Exception e) { + //e.printStackTrace(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, e.toString(), null, resp); + } + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_POLICY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + public void getPolicyInstanceConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get the policy rule id. + String id = req.getParameter(Constants.RS_ID).trim(); + + if (id == null) { + sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp); + return; + } + + Vector<String> v = mProcessor.getPolicyInstanceConfig(id); + + if (v == null) { + sendResponse(ERROR, INVALID_POLICY_INST_ID, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + for (Enumeration<String> e = v.elements(); e.hasMoreElements();) { + String nv = e.nextElement(); + int index = nv.indexOf("="); + String name = nv.substring(0, index); + String value = nv.substring(index + 1); + + if (value == null) { + value = ""; + } + + nvp.put(name, value); + + } + sendResponse(SUCCESS, null, nvp, resp); + } + + public void + putUserPWPair(String combo) { + int semicolon; + + semicolon = combo.indexOf(";"); + String user = combo.substring(0, semicolon); + String pw = combo.substring(semicolon + 1); + + CMS.putPasswordCache(user, pw); + } + + /** + * Add policy instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and + * extensions + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addPolicyInstance(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id and class path. + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp); + return; + } + + // Get the default config params for the implementation. + String implName = req.getParameter(IPolicyRule.PROP_IMPLNAME); + + if (implName == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + // We need to fetch parameters: enable, predicate and implname + // always, and any additional parameters as required by the + // implementation. + Hashtable<String, String> ht = new Hashtable<String, String>(); + String val = req.getParameter(IPolicyRule.PROP_ENABLE).trim(); + + if (val == null) + val = "true"; + ht.put(IPolicyRule.PROP_ENABLE, val); + + val = req.getParameter(IPolicyRule.PROP_PREDICATE); + if (val != null) + ht.put(IPolicyRule.PROP_PREDICATE, val); + ht.put(IPolicyRule.PROP_IMPLNAME, implName); + + Vector<String> v = mProcessor.getPolicyImplConfig(implName); + + if (v == null) { + // Invalid impl id + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, INVALID_POLICY_IMPL_ID, null, resp); + return; + } + for (Enumeration<String> e = v.elements(); e.hasMoreElements();) { + String nv = e.nextElement(); + int index = nv.indexOf("="); + String key = nv.substring(0, index); + + val = req.getParameter(key).trim(); + if (val != null) + ht.put(key, val); + } + + String pwadd = req.getParameter(PW_PASSWORD_CACHE_ADD); + + if (pwadd != null) { + putUserPWPair(pwadd); + } + + try { + mProcessor.addPolicyInstance(id, ht); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, e.toString(), null, resp); + } + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_POLICY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Change ordering of policy instances + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and + * extensions + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void changePolicyInstanceOrdering(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String policyOrder = + req.getParameter(Constants.PR_POLICY_ORDER); + + if (policyOrder == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_ORDERING, null, resp); + return; + } + try { + mProcessor.changePolicyInstanceOrdering(policyOrder); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, e.toString(), null, resp); + } + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_POLICY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Modify policy instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY used when configuring cert policy constraints and + * extensions + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void modifyPolicyInstance(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id and class path. + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp); + return; + } + + // Get the default config params for the implementation. + String implName = req.getParameter(IPolicyRule.PROP_IMPLNAME).trim(); + + if (implName == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + // We need to fetch parameters: enable, predicate and implname + // always, and any additional parameters as required by the + // implementation. + Hashtable<String, String> ht = new Hashtable<String, String>(); + String val = req.getParameter(IPolicyRule.PROP_ENABLE).trim(); + + if (val == null) + val = "true"; + ht.put(IPolicyRule.PROP_ENABLE, val); + + val = req.getParameter(IPolicyRule.PROP_PREDICATE); + if (val != null) + ht.put(IPolicyRule.PROP_PREDICATE, val); + ht.put(IPolicyRule.PROP_IMPLNAME, implName); + Vector<String> v = mProcessor.getPolicyImplConfig(implName); + + if (v == null) { + // Invalid impl id + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, INVALID_POLICY_IMPL_ID, null, resp); + return; + } + // XXX + for (@SuppressWarnings("unchecked") + Enumeration<String> n = req.getParameterNames(); n.hasMoreElements();) { + String p = n.nextElement(); + String l = req.getParameter(p); + + if (l != null) + ht.put(p, l); + } + + /* + for(Enumeration e = v.elements(); e.hasMoreElements(); ) + { + String nv = (String)e.nextElement(); + int index = nv.indexOf("="); + String key = nv.substring(0, index); + val = req.getParameter(key); + if (val != null) + ht.put(key, val); + } + */ + + try { + mProcessor.modifyPolicyInstance(id, ht); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, e.toString(), null, resp); + } + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_POLICY, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_POLICY, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java new file mode 100644 index 000000000..94235f532 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java @@ -0,0 +1,2682 @@ +// --- 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.admin; + +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileEx; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.profile.IProfileOutput; +import com.netscape.certsrv.profile.IProfilePolicy; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.property.EPropertyException; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.registry.IPluginInfo; +import com.netscape.certsrv.registry.IPluginRegistry; +import com.netscape.cms.profile.common.ProfilePolicy; + +/** + * This class is an administration servlet for policy management. + * + * Each service (CA, KRA, RA) should be responsible + * for registering an instance of this with the remote + * administration subsystem. + * + * @version $Revision$, $Date$ + */ +public class ProfileAdminServlet extends AdminServlet { + /** + * + */ + private static final long serialVersionUID = 4828203666899891742L; + + public final static String PROP_AUTHORITY = "authority"; + + private final static String INFO = "ProfileAdminServlet"; + private final static String PW_PASSWORD_CACHE_ADD = + "PASSWORD_CACHE_ADD"; + + public final static String PROP_PREDICATE = "predicate"; + private IAuthority mAuthority = null; + private IPluginRegistry mRegistry = null; + private IProfileSubsystem mProfileSub = null; + + // These will be moved to PolicyResources + public static String INVALID_POLICY_SCOPE = "Invalid policy administration scope"; + public static String INVALID_POLICY_IMPL_OP = "Invalid operation for policy implementation management"; + public static String NYI = "Not Yet Implemented"; + public static String INVALID_POLICY_IMPL_CONFIG = "Invalid policy implementation configuration"; + public static String INVALID_POLICY_INSTANCE_CONFIG = "Invalid policy instance configuration"; + public static String MISSING_POLICY_IMPL_ID = "Missing policy impl id in request"; + public static String MISSING_POLICY_IMPL_CLASS = "Missing policy impl class in request"; + public static String INVALID_POLICY_IMPL_ID = "Invalid policy impl id in request"; + public static String MISSING_POLICY_INST_ID = "Missing policy id in request"; + public static String POLICY_INST_ID_ALREADY_USED = "policy id already used"; + public static String INVALID_POLICY_INST_ID = "Invalid policy id in request"; + public static String COMMA = ","; + public static String MISSING_POLICY_ORDERING = "Missing policy ordering"; + public static String BAD_CONFIGURATION_VAL = "Invalid configuration value."; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE = + "LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE_3"; + + /** + * Constructs administration servlet. + */ + public ProfileAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + String authority = config.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) CMS.getSubsystem(authority); + mRegistry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY); + mProfileSub = (IProfileSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_PROFILE); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + super.authenticate(req); + + AUTHZ_RES_NAME = "certServer.profile.configuration"; + String scope = req.getParameter(Constants.OP_SCOPE); + + CMS.debug("ProfileAdminServlet: service scope: " + scope); + if (scope.equals(ScopeDef.SC_PROFILE_RULES)) { + processProfileRuleMgmt(req, resp); + } else if (scope.equals(ScopeDef.SC_PROFILE_POLICIES)) { + processProfilePolicy(req, resp); + } else if (scope.equals(ScopeDef.SC_PROFILE_DEFAULT_POLICY)) { + processPolicyDefaultConfig(req, resp); + } else if (scope.equals(ScopeDef.SC_PROFILE_CONSTRAINT_POLICY)) { + processPolicyConstraintConfig(req, resp); + } else if (scope.equals(ScopeDef.SC_POLICY_IMPLS)) { + processPolicyImplMgmt(req, resp); + } else if (scope.equals(ScopeDef.SC_PROFILE_INPUT)) { + processProfileInput(req, resp); + } else if (scope.equals(ScopeDef.SC_PROFILE_OUTPUT)) { + processProfileOutput(req, resp); + } else if (scope.equals(ScopeDef.SC_PROFILE_INPUT_CONFIG)) { + processProfileInputConfig(req, resp); + } else if (scope.equals(ScopeDef.SC_PROFILE_OUTPUT_CONFIG)) { + processProfileOutputConfig(req, resp); + } else + sendResponse(ERROR, INVALID_POLICY_SCOPE, null, resp); + } + + private boolean readAuthorize(HttpServletRequest req, + HttpServletResponse resp) throws IOException { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return false; + } + return true; + } + + private boolean modifyAuthorize(HttpServletRequest req, + HttpServletResponse resp) throws IOException { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return false; + } + return true; + } + + public void processProfilePolicy(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getProfilePolicy(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addProfilePolicy(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + if (!modifyAuthorize(req, resp)) + return; + deleteProfilePolicy(req, resp); + } + } + + public void processProfileInput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getProfileInput(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addProfileInput(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + if (!modifyAuthorize(req, resp)) + return; + deleteProfileInput(req, resp); + } + } + + public void processProfileOutput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getProfileOutput(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addProfileOutput(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + if (!modifyAuthorize(req, resp)) + return; + deleteProfileOutput(req, resp); + } + } + + public void processProfileInputConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getInputConfig(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + if (!modifyAuthorize(req, resp)) + return; + modifyInputConfig(req, resp); + } + } + + public void processProfileOutputConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getOutputConfig(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + if (!modifyAuthorize(req, resp)) + return; + modifyOutputConfig(req, resp); + } + } + + public void processPolicyDefaultConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getPolicyDefaultConfig(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addPolicyDefaultConfig(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + if (!modifyAuthorize(req, resp)) + return; + modifyPolicyDefaultConfig(req, resp); + } + } + + public void processPolicyConstraintConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + CMS.debug("ProfileAdminServlet: processPolicyConstraintConfig op " + op); + if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getPolicyConstraintConfig(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addPolicyConstraintConfig(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + if (!modifyAuthorize(req, resp)) + return; + modifyPolicyConstraintConfig(req, resp); + } + } + + /** + * Process Policy Implementation Management. + */ + public void processPolicyImplMgmt(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_SEARCH)) { + if (!readAuthorize(req, resp)) + return; + listProfileImpls(req, resp); + } else + sendResponse(ERROR, INVALID_POLICY_IMPL_OP, + null, resp); + } + + public void processProfileRuleMgmt(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_SEARCH)) { + if (!readAuthorize(req, resp)) + return; + listProfileInstances(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + if (!modifyAuthorize(req, resp)) + return; + deleteProfileInstance(req, resp); + } else if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getProfileInstanceConfig(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addProfileInstance(req, resp); + } else if (op.equals(OpDef.OP_MODIFY)) { + if (!modifyAuthorize(req, resp)) + return; + modifyProfileInstance(req, resp); + } else + sendResponse(ERROR, INVALID_POLICY_IMPL_OP, + null, resp); + } + + /** + * Lists all registered profile impementations + */ + public void listProfileImpls(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + Enumeration<String> impls = mRegistry.getIds("profile"); + NameValuePairs nvp = new NameValuePairs(); + + while (impls.hasMoreElements()) { + String id = (String) impls.nextElement(); + IPluginInfo info = mRegistry.getPluginInfo("profile", id); + + nvp.put(id, info.getClassName() + "," + + info.getDescription(getLocale(req))); + } + sendResponse(SUCCESS, null, nvp, resp); + } + + /** + * Add policy profile + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addProfilePolicy(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + CMS.debug("ProfileAdminServlet: in addProfilePolicy"); + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String policyId = st.nextToken(); + String defImpl = st.nextToken(); + String conImpl = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + if (mProfileSub.isProfileEnable(profileId)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), + "CMS_PROFILE_CREATE_POLICY_FAILED", + "Profile is currently enabled"), + null, resp); + return; + } + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + + try { + if (!isValidId(setId)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), + "CMS_PROFILE_CREATE_POLICY_FAILED", + "Invalid set id " + setId), + null, resp); + return; + } + if (!isValidId(pId)) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), + "CMS_PROFILE_CREATE_POLICY_FAILED", + "Invalid policy id " + pId), + null, resp); + return; + } + profile.createProfilePolicy(setId, pId, + defImpl, conImpl); + } catch (EBaseException e1) { + // error + CMS.debug("ProfileAdminServlet: addProfilePolicy " + + e1.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_PROFILE_CREATE_POLICY_FAILED", + e1.toString()), + null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Add profile input + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addProfileInput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String inputId = st.nextToken(); + String inputImpl = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + NameValuePairs nvps = new NameValuePairs(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + nvps.put(name, req.getParameter(name)); + } + + try { + profile.createProfileInput(inputId, inputImpl, nvps); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_PROFILE_CREATE_INPUT_FAILED", + e1.toString()), + null, resp); + + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Add profile output + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addProfileOutput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String outputId = st.nextToken(); + String outputImpl = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + NameValuePairs nvps = new NameValuePairs(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + nvps.put(name, req.getParameter(name)); + } + + try { + profile.createProfileOutput(outputId, outputImpl, + nvps); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_PROFILE_CREATE_OUTPUT_FAILED", + e1.toString()), + null, resp); + + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Delete policy profile + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void deleteProfilePolicy(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String profileId = ""; + String policyId = ""; + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + profileId = req.getParameter(name); + if (name.equals("POLICYID")) + policyId = req.getParameter(name); + } + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + + try { + profile.deleteProfilePolicy(setId, pId); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet: " + e1.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Delete profile input + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void deleteProfileInput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String profileId = ""; + String inputId = ""; + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + profileId = req.getParameter(name); + if (name.equals("INPUTID")) + inputId = req.getParameter(name); + } + CMS.debug("ProfileAdminServlet: deleteProfileInput profileId -> " + profileId); + CMS.debug("ProfileAdminServlet: deleteProfileInput inputId -> " + inputId); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + CMS.debug("deleteProfileInput profile -> " + profile); + try { + profile.deleteProfileInput(inputId); + } catch (EBaseException e1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Delete profile output + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void deleteProfileOutput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String profileId = ""; + String outputId = ""; + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + profileId = req.getParameter(name); + if (name.equals("OUTPUTID")) + outputId = req.getParameter(name); + } + CMS.debug("ProfileAdminServlet: deleteProfileOutput profileId -> " + profileId); + CMS.debug("ProfileAdminServlet: deleteProfileOutput outputId -> " + outputId); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + CMS.debug("ProfileAdminServlet: deleteProfileOutput profile -> " + profile); + try { + profile.deleteProfileOutput(outputId); + } catch (EBaseException e1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Add default policy profile configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addPolicyDefaultConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String policyId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + + IProfilePolicy policy = profile.getProfilePolicy(setId, pId); + IPolicyDefault def = policy.getDefault(); + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + try { + def.setConfig(name, req.getParameter(name)); + + } catch (EPropertyException e) { + + CMS.debug("ProfileAdminServlet: modifyPolicyDefConfig setConfig exception."); + try { + profile.deleteProfilePolicy(setId, pId); + } catch (Exception e11) { + } + sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp); + return; + } + // defConfig.putString("params." + name, req.getParameter(name)); + } + try { + profile.getConfigStore().commit(false); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Add policy constraints profile configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addPolicyConstraintConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String policyId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + + IProfilePolicy policy = profile.getProfilePolicy(setId, pId); + IPolicyConstraint con = policy.getConstraint(); + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + + try { + con.setConfig(name, req.getParameter(name)); + + } catch (EPropertyException e) { + + CMS.debug("ProfileAdminServlet: addPolicyConstraintsConfig setConfig exception."); + try { + profile.deleteProfilePolicy(setId, pId); + } catch (Exception e11) { + } + sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp); + return; + } + // conConfig.putString("params." + name, req.getParameter(name)); + } + try { + profile.getConfigStore().commit(false); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Modify default policy profile configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void modifyPolicyDefaultConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String policyId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + IProfilePolicy policy = profile.getProfilePolicy(setId, pId); + IPolicyDefault def = policy.getDefault(); + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + try { + def.setConfig(name, req.getParameter(name)); + + } catch (EPropertyException e) { + + CMS.debug("ProfileAdminServlet: modifyPolicyDefConfig setConfig exception."); + sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp); + return; + } + // defConfig.putString("params." + name, req.getParameter(name)); + } + try { + profile.getConfigStore().commit(false); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Modify profile input configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void modifyInputConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String inputId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + IProfileInput input = profile.getProfileInput(inputId); + IConfigStore inputConfig = input.getConfigStore(); + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + inputConfig.putString("params." + name, req.getParameter(name)); + } + try { + profile.getConfigStore().commit(false); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Modify profile output configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void modifyOutputConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String outputId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + IProfileOutput output = profile.getProfileOutput(outputId); + IConfigStore outputConfig = output.getConfigStore(); + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + outputConfig.putString("params." + name, + req.getParameter(name)); + } + try { + profile.getConfigStore().commit(false); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Modify policy constraints profile configuration + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void modifyPolicyConstraintConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String policyId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + IProfilePolicy policy = profile.getProfilePolicy(setId, pId); + IPolicyConstraint con = policy.getConstraint(); + + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + CMS.debug("ProfileAdminServlet: modifyPolicyConstraintConfig policy " + policy + " con " + con); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + if (name.equals("OP_SCOPE")) + continue; + if (name.equals("OP_TYPE")) + continue; + if (name.equals("RS_ID")) + continue; + + // CMS.debug("ProfileAdminServlet: modifyPolicyConstraintConfig name" + name + " val " + req.getParameter(name)); + try { + con.setConfig(name, req.getParameter(name)); + + } catch (EPropertyException e) { + + CMS.debug("ProfileAdminServlet: modifyPolicyConstraintsConfig setConfig exception."); + sendResponse(ERROR, BAD_CONFIGURATION_VAL, null, resp); + return; + } + //conConfig.putString("params." + name, req.getParameter(name)); + } + try { + profile.getConfigStore().commit(false); + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, nvp, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + public void getPolicyDefaultConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String id = req.getParameter(Constants.RS_ID); + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String policyId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getPolicyDefaultConfig() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + IProfilePolicy policy = null; + IPolicyDefault rule = null; + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + + policy = profile.getProfilePolicy(setId, pId); + rule = policy.getDefault(); + + NameValuePairs nvp = new NameValuePairs(); + Enumeration<String> names = rule.getConfigNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + IDescriptor desc = rule.getConfigDescriptor(getLocale(req), name); + + if (desc == null) { + nvp.put(name, ";" + ";" + rule.getConfig(name)); + } else { + nvp.put(name, + desc.getSyntax() + + ";" + ";" + getNonNull(desc.getConstraint()) + ";" + + desc.getDescription(getLocale(req)) + ";" + rule.getConfig(name)); + } + } + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getPolicyConstraintConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String id = req.getParameter(Constants.RS_ID); + String constraintsList = req.getParameter(Constants.PR_CONSTRAINTS_LIST); + + // this one gets called when one of the elements in the default list get + // selected, then it returns the list of supported constraintsPolicy + if (constraintsList != null) { + + } + + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String policyId = st.nextToken(); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getPolicyConstraintConfig() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + StringTokenizer ss = new StringTokenizer(policyId, ":"); + String setId = ss.nextToken(); + String pId = ss.nextToken(); + IProfilePolicy policy = profile.getProfilePolicy(setId, pId); + IPolicyConstraint rule = policy.getConstraint(); + + NameValuePairs nvp = new NameValuePairs(); + Enumeration<String> names = rule.getConfigNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + IDescriptor desc = rule.getConfigDescriptor(getLocale(req), name); + + if (desc == null) { + nvp.put(name, ";" + rule.getConfig(name)); + } else { + nvp.put(name, + desc.getSyntax() + + ";" + getNonNull(desc.getConstraint()) + ";" + desc.getDescription(getLocale(req)) + + ";" + rule.getConfig(name)); + } + } + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getProfilePolicy(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String id = req.getParameter(Constants.RS_ID); + + // only allow profile retrival if it is disabled + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(id); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getProfilePolicy() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + NameValuePairs nvp = new NameValuePairs(); + Enumeration<String> setIds = profile.getProfilePolicySetIds(); + + if (!setIds.hasMoreElements()) { + // no set id; this is a brand new profile + sendResponse(SUCCESS, null, nvp, resp); + return; + } + while (setIds.hasMoreElements()) { + String setId = (String) setIds.nextElement(); + Enumeration<ProfilePolicy> policies = profile.getProfilePolicies(setId); + + while (policies.hasMoreElements()) { + IProfilePolicy policy = (IProfilePolicy) policies.nextElement(); + IPolicyDefault def = policy.getDefault(); + IPolicyConstraint con = policy.getConstraint(); + + nvp.put(setId + ":" + policy.getId(), + def.getName(getLocale(req)) + ";" + + con.getName(getLocale(req))); + } + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getProfileOutput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String id = req.getParameter(Constants.RS_ID); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(id); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getProfileOutput() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + NameValuePairs nvp = new NameValuePairs(); + Enumeration<String> outputs = profile.getProfileOutputIds(); + + while (outputs.hasMoreElements()) { + String outputId = (String) outputs.nextElement(); + IProfileOutput output = profile.getProfileOutput(outputId); + + nvp.put(outputId, output.getName(getLocale(req))); + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getProfileInput(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String id = req.getParameter(Constants.RS_ID); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(id); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getProfileInput() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + NameValuePairs nvp = new NameValuePairs(); + Enumeration<String> inputs = profile.getProfileInputIds(); + + while (inputs.hasMoreElements()) { + String inputId = (String) inputs.nextElement(); + IProfileInput input = profile.getProfileInput(inputId); + + nvp.put(inputId, input.getName(getLocale(req))); + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getInputConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + String id = req.getParameter(Constants.RS_ID); + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String inputId = st.nextToken(); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getInputConfig() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + IProfileInput profileInput = null; + NameValuePairs nvp = new NameValuePairs(); + + profileInput = profile.getProfileInput(inputId); + Enumeration<String> names = profileInput.getConfigNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + IDescriptor desc = profileInput.getConfigDescriptor( + getLocale(req), name); + if (desc == null) { + nvp.put(name, ";" + ";" + profileInput.getConfig(name)); + } else { + nvp.put(name, desc.getSyntax() + ";" + + getNonNull(desc.getConstraint()) + ";" + + desc.getDescription(getLocale(req)) + ";" + + profileInput.getConfig(name)); + } + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getOutputConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + String id = req.getParameter(Constants.RS_ID); + StringTokenizer st = new StringTokenizer(id, ";"); + String profileId = st.nextToken(); + String outputId = st.nextToken(); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getOutputConfig() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + IProfileOutput profileOutput = null; + NameValuePairs nvp = new NameValuePairs(); + + profileOutput = profile.getProfileOutput(outputId); + Enumeration<String> names = profileOutput.getConfigNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + IDescriptor desc = profileOutput.getConfigDescriptor( + getLocale(req), name); + if (desc == null) { + nvp.put(name, ";" + ";" + profileOutput.getConfig(name)); + } else { + nvp.put(name, desc.getSyntax() + ";" + + getNonNull(desc.getConstraint()) + ";" + + desc.getDescription(getLocale(req)) + ";" + + profileOutput.getConfig(name)); + } + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + public void listProfileInstances(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + NameValuePairs nvp = new NameValuePairs(); + Enumeration<String> e = mProfileSub.getProfileIds(); + + while (e.hasMoreElements()) { + String profileId = e.nextElement(); + + String status = null; + + if (mProfileSub.isProfileEnable(profileId)) { + status = "enabled"; + } else { + status = "disabled"; + } + + // mInstanceId + ";visible;" + enabled + nvp.put(profileId, profileId + ";visible;" + status); + } + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getProfileInstanceConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + String id = req.getParameter(Constants.RS_ID); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(id); + } catch (EBaseException e1) { + CMS.debug("ProfileAdminServlet::getProfileInstanceConfig() - " + + "profile is null!"); + throw new ServletException(e1.toString()); + } + + NameValuePairs nvp = new NameValuePairs(); + + nvp.put("name", profile.getName(getLocale(req))); + nvp.put("desc", profile.getDescription(getLocale(req))); + nvp.put("visible", Boolean.toString(profile.isVisible())); + nvp.put("enable", Boolean.toString( + mProfileSub.isProfileEnable(id))); + + String authid = profile.getAuthenticatorId(); + + if (authid == null) { + nvp.put("auth", ""); + } else { + nvp.put("auth", authid); + } + CMS.debug("ProfileAdminServlet: authid=" + authid); + nvp.put("plugin", mProfileSub.getProfileClassId(id)); + + sendResponse(SUCCESS, null, nvp, resp); + } + + /** + * Delete profile instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void deleteProfileInstance(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id and class path. + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp); + return; + } + + String config = null; + + ISubsystem subsystem = CMS.getSubsystem("ca"); + String subname = "ca"; + + if (subsystem == null) + subname = "ra"; + + try { + config = CMS.getConfigStore().getString("instanceRoot") + + "/profiles/" + subname + "/" + id + ".cfg"; + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + try { + mProfileSub.deleteProfile(id, config); + } catch (EProfileException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), e.toString(), id), null, resp); + return; + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + public void + putUserPWPair(String combo) { + int semicolon; + + semicolon = combo.indexOf(";"); + String user = combo.substring(0, semicolon); + String pw = combo.substring(semicolon + 1); + + CMS.putPasswordCache(user, pw); + } + + public boolean isValidId(String id) { + for (int i = 0; i < id.length(); i++) { + char c = id.charAt(i); + if (!Character.isLetterOrDigit(c)) + return false; + } + return true; + } + + /** + * Add profile instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void addProfileInstance(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id and class path. + String id = req.getParameter(Constants.RS_ID); + + if (id == null || id.trim().equals("") || !isValidId(id)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, MISSING_POLICY_INST_ID, null, resp); + return; + } + + // see if profile id already used + IProfile p = null; + + try { + p = mProfileSub.getProfile(id); + } catch (EProfileException e1) { + } + if (p != null) { + sendResponse(ERROR, POLICY_INST_ID_ALREADY_USED, null, resp); + return; + } + + String impl = req.getParameter("impl"); + String name = req.getParameter("name"); + String visible = req.getParameter("visible"); + String auth = req.getParameter("auth"); + String config = null; + + ISubsystem subsystem = CMS.getSubsystem("ca"); + String subname = "ca"; + + if (subsystem == null) + subname = "ra"; + + try { + config = CMS.getConfigStore().getString("instanceRoot") + "/profiles/" + subname + "/" + id + ".cfg"; + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + IPluginInfo info = mRegistry.getPluginInfo("profile", impl); + + IProfile profile = null; + + // create configuration file + File configFile = new File(config); + + configFile.createNewFile(); + + // create profile + try { + profile = mProfileSub.createProfile(id, impl, + info.getClassName(), + config); + profile.setName(getLocale(req), name); + profile.setDescription(getLocale(req), name); + if (visible != null && visible.equals("true")) { + profile.setVisible(true); + } else { + profile.setVisible(false); + } + profile.setAuthenticatorId(auth); + profile.getConfigStore().commit(false); + + mProfileSub.createProfileConfig(id, impl, config); + if (profile instanceof IProfileEx) { + // populates profile specific plugins such as + // policies, inputs and outputs + ((IProfileEx) profile).populate(); + } + } catch (Exception e) { + CMS.debug("ProfileAdminServlet: " + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, null, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + /** + * Modify profile instance + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE used when configuring cert profile (general settings + * and cert profile; obsoletes extensions and constraints policies) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + */ + public void modifyProfileInstance(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // Get the policy impl id and class path. + String id = req.getParameter(Constants.RS_ID); + + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(id); + } catch (EBaseException e1) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, null, null, resp); + return; + } + String name = req.getParameter("name"); + String desc = req.getParameter("desc"); + String auth = req.getParameter("auth"); + String visible = req.getParameter("visible"); + + // String config = req.getParameter("config"); + + profile.setAuthenticatorId(auth); + profile.setName(getLocale(req), name); + profile.setDescription(getLocale(req), desc); + if (visible != null && visible.equals("true")) { + profile.setVisible(true); + } else { + profile.setVisible(false); + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + try { + profile.getConfigStore().commit(false); + } catch (Exception e) { + } + + sendResponse(SUCCESS, null, null, resp); + } catch (IOException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_CERT_PROFILE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + 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_CONFIG_CERT_PROFILE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + } + + protected String getNonNull(String s) { + if (s == null) + return ""; + return s; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java new file mode 100644 index 000000000..483ac42ef --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java @@ -0,0 +1,3127 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPException; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.ExtendedPluginInfo; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.Plugin; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.common.ConfigConstants; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.ldap.ELdapException; +import com.netscape.certsrv.ldap.ILdapAuthInfo; +import com.netscape.certsrv.ldap.ILdapBoundConnFactory; +import com.netscape.certsrv.ldap.ILdapConnInfo; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.EMapperNotFound; +import com.netscape.certsrv.publish.EMapperPluginNotFound; +import com.netscape.certsrv.publish.EPublisherNotFound; +import com.netscape.certsrv.publish.EPublisherPluginNotFound; +import com.netscape.certsrv.publish.ERuleNotFound; +import com.netscape.certsrv.publish.ERulePluginNotFound; +import com.netscape.certsrv.publish.ILdapMapper; +import com.netscape.certsrv.publish.ILdapPublisher; +import com.netscape.certsrv.publish.ILdapRule; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.publish.MapperPlugin; +import com.netscape.certsrv.publish.MapperProxy; +import com.netscape.certsrv.publish.PublisherPlugin; +import com.netscape.certsrv.publish.PublisherProxy; +import com.netscape.certsrv.publish.RulePlugin; +import com.netscape.certsrv.security.ICryptoSubsystem; +import com.netscape.cmsutil.password.IPasswordStore; + +/** + * A class representing an publishing servlet for the + * Publishing subsystem. This servlet is responsible + * to serve configuration requests for the Publishing subsystem. + * + * @version $Revision$, $Date$ + */ +public class PublisherAdminServlet extends AdminServlet { + /** + * + */ + private static final long serialVersionUID = 7055088618787207262L; + + public final static String PROP_AUTHORITY = "authority"; + + private final static String INFO = "PublisherAdminServlet"; + private final static String PW_TAG_CA_LDAP_PUBLISHING = + "CA LDAP Publishing"; + public final static String NOMAPPER = "<NONE>"; + private IPublisherProcessor mProcessor = null; + private IAuthority mAuth = null; + + private final static String VIEW = ";" + Constants.VIEW; + private final static String EDIT = ";" + Constants.EDIT; + + public PublisherAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + String authority = config.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuth = (IAuthority) CMS.getSubsystem(authority); + if (mAuth != null) + if (mAuth instanceof ICertificateAuthority) { + mProcessor = ((ICertificateAuthority) mAuth).getPublisherProcessor(); + } else + throw new ServletException(authority + " does not have publishing processor!"); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + CMS.debug("PublisherAdminServlet: in service"); + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + if (op == null) { + //System.out.println("SRVLT_INVALID_PROTOCOL"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + return; + } + + // for the rest + try { + super.authenticate(req); + + if (op.equals(OpDef.OP_AUTH)) { // for admin authentication only + sendResponse(SUCCESS, null, null, resp); + return; + } + } catch (IOException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"), + null, resp); + return; + } + try { + AUTHZ_RES_NAME = "certServer.publisher.configuration"; + if (scope != null) { + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_LDAP)) { + getLDAPDest(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) { + getConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) { + getInstConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) { + getMapperConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) { + getMapperInstConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) { + getRuleConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_EXTENDED_PLUGIN_INFO)) { + getExtendedPluginInfo(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_RULE_RULES)) { + getRuleInstConfig(req, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_LDAP)) { + setLDAPDest(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) { + modPublisherInst(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) { + modMapperInst(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_RULE_RULES)) { + modRuleInst(req, resp, scope); + return; + } + } else if (op.equals(OpDef.OP_PROCESS)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_LDAP)) { + testSetLDAPDest(req, resp); + return; + } + } else if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) { + listPublisherPlugins(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) { + listPublisherInsts(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) { + listMapperPlugins(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) { + listMapperInsts(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) { + listRulePlugins(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_RULE_RULES)) { + listRuleInsts(req, resp); + return; + } + } else if (op.equals(OpDef.OP_ADD)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) { + addPublisherPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) { + addPublisherInst(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) { + addMapperPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) { + addMapperInst(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) { + addRulePlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_RULE_RULES)) { + addRuleInst(req, resp, scope); + return; + } + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_PUBLISHER_IMPLS)) { + delPublisherPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_PUBLISHER_RULES)) { + delPublisherInst(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_IMPLS)) { + delMapperPlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_MAPPER_RULES)) { + delMapperInst(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_RULE_IMPLS)) { + delRulePlugin(req, resp, scope); + return; + } else if (scope.equals(ScopeDef.SC_RULE_RULES)) { + delRuleInst(req, resp, scope); + return; + } + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_TYPE", op), + null, resp); + return; + } + } else { + //System.out.println("SRVLT_INVALID_OP_SCOPE"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } catch (EBaseException e) { + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } + //System.out.println("SRVLT_FAIL_PERFORM 2"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"), + null, resp); + return; + } + + private IExtendedPluginInfo getExtendedPluginInfo(IPublisherProcessor + p) { + Enumeration<String> mappers = p.getMapperInsts().keys(); + Enumeration<String> publishers = p.getPublisherInsts().keys(); + + StringBuffer map = new StringBuffer(); + + for (; mappers.hasMoreElements();) { + String name = mappers.nextElement(); + + if (map.length() == 0) { + map.append(name); + } else { + map.append(","); + map.append(name); + } + } + StringBuffer publish = new StringBuffer(); + + for (; publishers.hasMoreElements();) { + String name = (String) publishers.nextElement(); + + publish.append(","); + publish.append(name); + } + + String epi[] = new String[] { + "type;choice(cacert,crl,certs,xcert);The certType of the request", + "mapper;choice(" + + map.toString() + + ");Use the mapper to find the ldap dn to publish the certificate or crl", + "publisher;choice(" + + publish.toString() + + ");Use the publisher to publish the certificate or crl a directory etc", + "enable;boolean;", + "predicate;string;" + }; + + return new ExtendedPluginInfo(epi); + } + + private NameValuePairs getExtendedPluginInfo(Locale locale, String implType, String implName) { + IExtendedPluginInfo ext_info = null; + Object impl = null; + + if (implType.equals(Constants.PR_EXT_PLUGIN_IMPLTYPE_PUBLISHRULE)) { + IPublisherProcessor p_processor = mProcessor; + + // Should get the registered rules from processor + // instead of plugin + // OLD: impl = getClassByNameAsExtendedPluginInfo(plugin.getClassPath()); + impl = getExtendedPluginInfo(p_processor); + } else if (implType.equals(Constants.PR_EXT_PLUGIN_IMPLTYPE_MAPPER)) { + IPublisherProcessor p_processor = mProcessor; + Plugin plugin = (Plugin) p_processor.getMapperPlugins().get(implName + ); + + impl = getClassByNameAsExtendedPluginInfo(plugin.getClassPath()); + + } else if (implType.equals(Constants.PR_EXT_PLUGIN_IMPLTYPE_PUBLISHER)) { + IPublisherProcessor p_processor = mProcessor; + Plugin plugin = (Plugin) p_processor.getPublisherPlugins().get(implName); + + impl = getClassByNameAsExtendedPluginInfo(plugin.getClassPath()); + } + if (impl != null) { + if (impl instanceof IExtendedPluginInfo) { + ext_info = (IExtendedPluginInfo) impl; + } + } + + NameValuePairs nvps = null; + + if (ext_info == null) { + nvps = new NameValuePairs(); + } else { + nvps = convertStringArrayToNVPairs(ext_info.getExtendedPluginInfo(locale)); + } + + return nvps; + + } + + /** + * retrieve extended plugin info such as brief description, type info + * from policy, authentication, + * need to add: listener, mapper and publishing plugins + */ + private void getExtendedPluginInfo(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + int colon = id.indexOf(':'); + + String implType = id.substring(0, colon); + String implName = id.substring(colon + 1); + + NameValuePairs params = + getExtendedPluginInfo(getLocale(req), implType, implName); + + sendResponse(SUCCESS, null, params, resp); + } + + private void getLDAPDest(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + IConfigStore config = mAuth.getConfigStore(); + IConfigStore publishcfg = config.getSubStore(IPublisherProcessor.PROP_PUBLISH_SUBSTORE); + IConfigStore ldapcfg = publishcfg.getSubStore(IPublisherProcessor.PROP_LDAP_PUBLISH_SUBSTORE); + IConfigStore ldap = ldapcfg.getSubStore(IPublisherProcessor.PROP_LDAP); + + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + if (name.equals(Constants.PR_PUBLISHING_ENABLE)) + continue; + if (name.equals(Constants.PR_PUBLISHING_QUEUE_ENABLE)) + continue; + if (name.equals(Constants.PR_PUBLISHING_QUEUE_THREADS)) + continue; + if (name.equals(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE)) + continue; + if (name.equals(Constants.PR_PUBLISHING_QUEUE_PRIORITY)) + continue; + if (name.equals(Constants.PR_PUBLISHING_QUEUE_STATUS)) + continue; + if (name.equals(Constants.PR_CERT_NAMES)) { + ICryptoSubsystem jss = (ICryptoSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + params.put(name, jss.getAllCerts()); + } else { + String value = ldap.getString(name, ""); + + if (value == null || value.equals("")) { + if (name.equals(ILdapBoundConnFactory.PROP_LDAPCONNINFO + "." + ILdapConnInfo.PROP_HOST)) { + value = mConfig.getString(ConfigConstants.PR_MACHINE_NAME, null); + } else if (name.equals(ILdapBoundConnFactory.PROP_LDAPCONNINFO + "." + ILdapConnInfo.PROP_PORT)) { + value = ILdapConnInfo.PROP_PORT_DEFAULT; + } else if (name.equals(ILdapBoundConnFactory.PROP_LDAPAUTHINFO + "." + ILdapAuthInfo.PROP_BINDDN)) { + value = ILdapAuthInfo.PROP_BINDDN_DEFAULT; + } + } + params.put(name, value); + } + } + params.put(Constants.PR_PUBLISHING_ENABLE, + publishcfg.getString(IPublisherProcessor.PROP_ENABLE, Constants.FALSE)); + params.put(Constants.PR_PUBLISHING_QUEUE_ENABLE, + publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_ENABLE, Constants.TRUE)); + params.put(Constants.PR_PUBLISHING_QUEUE_THREADS, + publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_THREADS, "3")); + params.put(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE, + publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE, "40")); + params.put(Constants.PR_PUBLISHING_QUEUE_PRIORITY, + publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_PRIORITY, "0")); + params.put(Constants.PR_PUBLISHING_QUEUE_STATUS, + publishcfg.getString(Constants.PR_PUBLISHING_QUEUE_STATUS, "200")); + params.put(Constants.PR_ENABLE, + ldapcfg.getString(IPublisherProcessor.PROP_ENABLE, Constants.FALSE)); + sendResponse(SUCCESS, null, params, resp); + } + + private void setLDAPDest(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + + //Save New Settings to the config file + IConfigStore config = mAuth.getConfigStore(); + IConfigStore publishcfg = config.getSubStore(IPublisherProcessor.PROP_PUBLISH_SUBSTORE); + IConfigStore ldapcfg = publishcfg.getSubStore(IPublisherProcessor.PROP_LDAP_PUBLISH_SUBSTORE); + IConfigStore ldap = ldapcfg.getSubStore(IPublisherProcessor.PROP_LDAP); + + //set enable flag + publishcfg.putString(IPublisherProcessor.PROP_ENABLE, req.getParameter(Constants.PR_PUBLISHING_ENABLE)); + String enable = req.getParameter(Constants.PR_ENABLE); + + ldapcfg.putString(IPublisherProcessor.PROP_ENABLE, enable); + if (enable.equals("false")) { + // need to disable the ldap module here + mProcessor.setLdapConnModule(null); + } + + //set reset of the parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + String pwd = null; + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + if (name.equals(Constants.PR_PUBLISHING_ENABLE)) + continue; + // don't store password in the config file. + if (name.equals(Constants.PR_BIND_PASSWD)) + continue; // old style password read from config. + if (name.equals(Constants.PR_DIRECTORY_MANAGER_PWD)) { + pwd = req.getParameter(name); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_ENABLE)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_THREADS)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_PRIORITY)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_STATUS)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + + /* Don't enter the publishing pw into the config store */ + ldap.putString(name, req.getParameter(name)); + } + + commit(true); + + /* Do a "PUT" of the new pw to the watchdog" + ** do not remove - cfu + if (pwd != null) + CMS.putPasswordCache(PW_TAG_CA_LDAP_PUBLISHING, pwd); + */ + + // support publishing dirsrv with different pwd than internaldb + // update passwordFile + String prompt = ldap.getString(Constants.PR_BINDPWD_PROMPT); + IPasswordStore pwdStore = CMS.getPasswordStore(); + CMS.debug("PublisherAdminServlet: setLDAPDest(): saving password for " + prompt + " to password file"); + pwdStore.putPassword(prompt, pwd); + pwdStore.commit(); + CMS.debug("PublisherAdminServlet: setLDAPDest(): password saved"); + + /* we'll shut down and restart the PublisherProcessor instead + // what a hack to do this without require restart server + // ILdapAuthInfo authInfo = CMS.getLdapAuthInfo(); + ILdapConnModule connModule = mProcessor.getLdapConnModule(); + ILdapAuthInfo authInfo = null; + if (connModule != null) { + authInfo = connModule.getLdapAuthInfo(); + } + + // authInfo.addPassword(PW_TAG_CA_LDAP_PUBLISHING, pwd); + if (authInfo != null) { + CMS.debug("PublisherAdminServlet: setLDAPDest(): adding password to memory cache"); + authInfo.addPassword(prompt, pwd); + } else + CMS.debug("PublisherAdminServlet: setLDAPDest(): authInfo null"); + */ + + try { + CMS.debug("PublisherAdminServlet: setLDAPDest(): restarting publishing processor"); + mProcessor.shutdown(); + mProcessor.startup(); + CMS.debug("PublisherAdminServlet: setLDAPDest(): publishing processor restarted"); + } catch (Exception ex) { + // force to save the config even there is error + // ignore any exception + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_RES_LDAP", ex.toString())); + } + + //XXX See if we can dynamically in B2 + sendResponse(SUCCESS, null, null, resp); + } + + private void testSetLDAPDest(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + CMS.debug("PublisherAdmineServlet: in testSetLDAPDest"); + //Save New Settings to the config file + IConfigStore config = mAuth.getConfigStore(); + IConfigStore publishcfg = config.getSubStore(IPublisherProcessor.PROP_PUBLISH_SUBSTORE); + IConfigStore ldapcfg = publishcfg.getSubStore(IPublisherProcessor.PROP_LDAP_PUBLISH_SUBSTORE); + IConfigStore ldap = ldapcfg.getSubStore(IPublisherProcessor.PROP_LDAP); + + //set enable flag + publishcfg.putString(IPublisherProcessor.PROP_ENABLE, + req.getParameter(Constants.PR_PUBLISHING_ENABLE)); + String ldapPublish = req.getParameter(Constants.PR_ENABLE); + + ldapcfg.putString(IPublisherProcessor.PROP_ENABLE, ldapPublish); + if (ldapPublish.equals("false")) { + // need to disable the ldap module here + mProcessor.setLdapConnModule(null); + } + + //set reset of the parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + String pwd = null; + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + if (name.equals(Constants.PR_PUBLISHING_ENABLE)) + continue; + // don't store password in the config file. + if (name.equals(Constants.PR_BIND_PASSWD)) + continue; // old style password read from config. + if (name.equals(Constants.PR_DIRECTORY_MANAGER_PWD)) { + pwd = req.getParameter(name); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_ENABLE)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_THREADS)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_PAGE_SIZE)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_PRIORITY)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + if (name.equals(Constants.PR_PUBLISHING_QUEUE_STATUS)) { + publishcfg.putString(name, req.getParameter(name)); + continue; + } + + /* Don't enter the publishing pw into the config store */ + ldap.putString(name, req.getParameter(name)); + } + + // test before commit + if (publishcfg.getBoolean(IPublisherProcessor.PROP_ENABLE) && + ldapcfg.getBoolean(IPublisherProcessor.PROP_ENABLE)) { + params.put("title", + "You've attempted to configure CMS to connect" + + " to a LDAP directory. The connection status is" + + " as follows:\n \n"); + LDAPConnection conn = null; + ILdapConnInfo connInfo = + CMS.getLdapConnInfo(ldap.getSubStore( + ILdapBoundConnFactory.PROP_LDAPCONNINFO)); + //LdapAuthInfo authInfo = + //new LdapAuthInfo(ldap.getSubStore( + // ILdapBoundConnFactory.PROP_LDAPAUTHINFO)); + String host = connInfo.getHost(); + int port = connInfo.getPort(); + boolean secure = connInfo.getSecure(); + //int authType = authInfo.getAuthType(); + String authType = ldap.getSubStore( + ILdapBoundConnFactory.PROP_LDAPAUTHINFO).getString(ILdapAuthInfo.PROP_LDAPAUTHTYPE); + int version = connInfo.getVersion(); + String bindAs = null; + String certNickName = null; + + if (authType.equals(ILdapAuthInfo.LDAP_SSLCLIENTAUTH_STR)) { + try { + //certNickName = authInfo.getParms()[0]; + certNickName = + ldap.getSubStore( + ILdapBoundConnFactory.PROP_LDAPAUTHINFO).getString( + ILdapAuthInfo.PROP_CLIENTCERTNICKNAME); + conn = new LDAPConnection(CMS.getLdapJssSSLSocketFactory( + certNickName)); + CMS.debug("Publishing Test certNickName=" + certNickName); + params.put(Constants.PR_CONN_INITED, + "Create ssl LDAPConnection with certificate: " + + certNickName + dashes(70 - 44 - certNickName.length()) + " Success"); + } catch (Exception ex) { + params.put(Constants.PR_CONN_INIT_FAIL, + "Create ssl LDAPConnection with certificate: " + + + certNickName + dashes(70 - 44 - certNickName.length()) + " failure\n" + + " exception: " + ex); + params.put(Constants.PR_SAVE_NOT, + "\n \nIf the problem is not fixed then LDAP publishing will fail.\n" + + "Do you want to save the configuration anyway?"); + sendResponse(SUCCESS, null, params, resp); + return; + } + try { + conn.connect(host, port); + params.put(Constants.PR_CONN_OK, + "Connect to directory server " + + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + + " Success"); + params.put(Constants.PR_AUTH_OK, + "Authentication: SSL client authentication" + + dashes(70 - 41) + " Success" + + "\nBind to the directory as: " + certNickName + + dashes(70 - 26 - certNickName.length()) + " Success"); + } catch (LDAPException ex) { + if (ex.getLDAPResultCode() == LDAPException.UNAVAILABLE) { + // need to intercept this because message from LDAP is + // "DSA is unavailable" which confuses with DSA PKI. + params.put(Constants.PR_CONN_FAIL, + "Connect to directory server " + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + + " Failure\n" + + " error: server unavailable"); + } else { + params.put(Constants.PR_CONN_FAIL, + "Connect to directory server " + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + + " Failure"); + } + params.put(Constants.PR_SAVE_NOT, + "\n \nIf the problem is not fixed then " + + "LDAP publishing will fail.\n" + + "Do you want to save the configuration anyway?"); + sendResponse(SUCCESS, null, params, resp); + return; + } + } else { + try { + if (secure) { + conn = new LDAPConnection( + CMS.getLdapJssSSLSocketFactory()); + params.put(Constants.PR_CONN_INITED, + "Create ssl LDAPConnection" + + dashes(70 - 25) + " Success"); + } else { + conn = new LDAPConnection(); + params.put(Constants.PR_CONN_INITED, + "Create LDAPConnection" + + dashes(70 - 21) + " Success"); + } + } catch (Exception ex) { + params.put(Constants.PR_CONN_INIT_FAIL, + "Create LDAPConnection" + + dashes(70 - 21) + " Failure\n" + + "exception: " + ex); + params.put(Constants.PR_SAVE_NOT, + "\n \nIf the problem is not fixed then " + + "LDAP publishing will fail.\n" + + "Do you want to save the configuration anyway?"); + sendResponse(SUCCESS, null, params, resp); + return; + } + try { + conn.connect(host, port); + params.put(Constants.PR_CONN_OK, + "Connect to directory server " + + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + + " Success"); + } catch (LDAPException ex) { + if (ex.getLDAPResultCode() == LDAPException.UNAVAILABLE) { + // need to intercept this because message from LDAP is + // "DSA is unavailable" which confuses with DSA PKI. + params.put(Constants.PR_CONN_FAIL, + "Connect to directory server " + + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + + " Failure" + + "\nerror: server unavailable"); + } else { + params.put(Constants.PR_CONN_FAIL, + "Connect to directory server " + + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + + " Failure" + + "\nexception: " + ex); + } + params.put(Constants.PR_SAVE_NOT, + "\n \nIf the problem is not fixed then " + + "LDAP publishing will fail.\n" + + "Do you want to save the configuration anyway?"); + sendResponse(SUCCESS, null, params, resp); + return; + } + try { + //bindAs = authInfo.getParms()[0]; + bindAs = ldap.getSubStore( + ILdapBoundConnFactory.PROP_LDAPAUTHINFO).getString(ILdapAuthInfo.PROP_BINDDN); + conn.authenticate(version, bindAs, pwd); + params.put(Constants.PR_AUTH_OK, + "Authentication: Basic authentication" + + dashes(70 - 36) + " Success" + + "\nBind to the directory as: " + bindAs + + dashes(70 - 26 - bindAs.length()) + " Success"); + } catch (LDAPException ex) { + if (ex.getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT) { + params.put(Constants.PR_AUTH_FAIL, + "Authentication: Basic authentication" + + dashes(70 - 36) + "Failure" + + "\nBind to the directory as: " + bindAs + + dashes(70 - 26 - bindAs.length()) + + "Failure" + "\nThe object doesn't exist. " + + "Please correct the value assigned in the" + + " \"Directory manager DN\" field."); + } else if (ex.getLDAPResultCode() == LDAPException.INVALID_CREDENTIALS) { + params.put(Constants.PR_AUTH_FAIL, + "Authentication: Basic authentication" + + dashes(70 - 36) + " Failure" + + "\nBind to the directory as: " + bindAs + + dashes(70 - 26 - bindAs.length()) + + " Failure" + "\nInvalid password. " + + "Please correct the value assigned in the" + + " \"Password\" field."); + } else { + params.put(Constants.PR_AUTH_FAIL, + "Authentication: Basic authentication" + + dashes(70 - 36) + " Failure" + + "\nBind to the directory as: " + bindAs + + dashes(70 - 26 - bindAs.length()) + + " Failure"); + } + params.put(Constants.PR_SAVE_NOT, + "\n \nIf the problem is not fixed then " + + "LDAP publishing will fail.\n" + + "Do you want to save the configuration anyway?"); + sendResponse(SUCCESS, null, params, resp); + return; + } + } + + } + + //commit(true); + if (ldapcfg.getBoolean(IPublisherProcessor.PROP_ENABLE) && + pwd != null) { + + /* Do a "PUT" of the new pw to the watchdog" + ** do not remove - cfu + CMS.putPasswordCache(PW_TAG_CA_LDAP_PUBLISHING, pwd); + */ + + // support publishing dirsrv with different pwd than internaldb + // update passwordFile + String prompt = ldap.getString(Constants.PR_BINDPWD_PROMPT); + IPasswordStore pwdStore = CMS.getPasswordStore(); + CMS.debug("PublisherAdminServlet: testSetLDAPDest(): saving password for " + + prompt + " to password file"); + pwdStore.putPassword(prompt, pwd); + pwdStore.commit(); + CMS.debug("PublisherAdminServlet: testSetLDAPDest(): password saved"); + /* we'll shut down and restart the PublisherProcessor instead + // what a hack to do this without require restart server + // ILdapAuthInfo authInfo = CMS.getLdapAuthInfo(); + ILdapConnModule connModule = mProcessor.getLdapConnModule(); + ILdapAuthInfo authInfo = null; + if (connModule != null) { + authInfo = connModule.getLdapAuthInfo(); + } else + CMS.debug("PublisherAdminServlet: testSetLDAPDest(): connModule null"); + + // authInfo.addPassword(PW_TAG_CA_LDAP_PUBLISHING, pwd); + if (authInfo != null) { + CMS.debug("PublisherAdminServlet: testSetLDAPDest(): adding password to memory cache"); + authInfo.addPassword(prompt, pwd); + } else + CMS.debug("PublisherAdminServlet: testSetLDAPDest(): authInfo null"); + */ + } + //params.add(Constants.PR_SAVE_OK, + // "\n \nConfiguration changes are now committed."); + + mProcessor.shutdown(); + + if (publishcfg.getBoolean(IPublisherProcessor.PROP_ENABLE)) { + mProcessor.startup(); + //params.add("restarted", "Publishing is restarted."); + + if (ldapcfg.getBoolean(IPublisherProcessor.PROP_ENABLE)) { + ICertAuthority authority = (ICertAuthority) mProcessor.getAuthority(); + + if (!(authority instanceof ICertificateAuthority)) + return; + ICertificateAuthority ca = (ICertificateAuthority) authority; + + // publish ca cert + try { + mProcessor.publishCACert(ca.getCACert()); + CMS.debug("PublisherAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_PUB_CA_CERT")); + params.put("publishCA", + "CA certificate is published."); + } catch (Exception ex) { + // exception not thrown - not seen as a fatal error. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_NO_PUB_CA_CERT", ex.toString())); + params.put("publishCA", + "Failed to publish CA certificate."); + int index = ex.toString().indexOf("Failed to create CA"); + + if (index > -1) { + params.put("createError", + ex.toString().substring(index)); + } + mProcessor.shutdown(); + // Do you want to enable LDAP publishing anyway + params.put(Constants.PR_SAVE_NOT, + "\n \nIf the problem is not fixed then " + + "the CA certificate won't be published.\n" + + "Do you want to enable LDAP publishing anyway?"); + sendResponse(SUCCESS, null, params, resp); + return; + + } + // publish crl + try { + CMS.debug("PublisherAdminServlet: about to update CRL"); + ca.publishCRLNow(); + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_PUB_CRL")); + params.put("publishCRL", + "CRL is published."); + } catch (Exception ex) { + // exception not thrown - not seen as a fatal error. + log(ILogger.LL_FAILURE, + "Could not publish crl " + ex.toString()); + params.put("publishCRL", + "Failed to publish CRL."); + mProcessor.shutdown(); + // Do you want to enable LDAP publishing anyway + params.put(Constants.PR_SAVE_NOT, + "\n \nIf the problem is not fixed then " + + "the CRL won't be published.\n" + + "Do you want to enable LDAP publishing anyway?"); + sendResponse(SUCCESS, null, params, resp); + return; + } + } + commit(true); + params.put(Constants.PR_SAVE_OK, + "\n \nConfiguration changes are now committed."); + params.put("restarted", "Publishing is restarted."); + } else { + commit(true); + params.put(Constants.PR_SAVE_OK, + "\n \nConfiguration changes are now committed."); + params.put("stopped", + "Publishing is stopped."); + } + + //XXX See if we can dynamically in B2 + sendResponse(SUCCESS, null, params, resp); + } + + private synchronized void addMapperPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // is the manager id unique? + if (mProcessor.getMapperPlugins().containsKey((Object) id)) { + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_PLUGIN_ID", id)) + .toString(), + null, resp); + return; + } + + String classPath = req.getParameter(Constants.PR_MAPPER_CLASS); + + if (classPath == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NULL_CLASS"), null, resp); + return; + } + + IConfigStore destStore = null; + + destStore = mConfig.getSubStore(mAuth.getId() + ".publish.mapper"); + IConfigStore instancesConfig = destStore.getSubStore("impl"); + + // Does the class exist? + Class<?> newImpl = null; + + try { + newImpl = Class.forName(classPath); + } catch (ClassNotFoundException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp); + return; + } catch (IllegalArgumentException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp); + return; + } + + // is the class an ILdapMapper? + try { + if (ILdapMapper.class.isAssignableFrom(newImpl) == false) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, + resp); + return; + } + } catch (NullPointerException e) { // unlikely, only if newImpl null. + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, resp); + return; + } + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(Constants.PR_MAPPER_CLASS, classPath); + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // add mapper to registry. + MapperPlugin plugin = new MapperPlugin(id, classPath); + + mProcessor.getMapperPlugins().put(id, plugin); + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_MAPPER_ADDED", "")); + + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private boolean isValidID(String id) { + if (id == null) + return false; + for (int i = 0; i < id.length(); i++) { + if (!Character.isLetterOrDigit(id.charAt(i))) + return false; + } + return true; + } + + private synchronized void addMapperInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + if (!isValidID(id)) { + sendResponse(ERROR, "Invalid ID '" + id + "'", + null, resp); + return; + } + + if (mProcessor.getMapperInsts().containsKey((Object) id)) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id), + null, resp); + return; + } + + // get required parameters + String implname = req.getParameter( + Constants.PR_MAPPER_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp); + return; + } + + // check if implementation exists. + MapperPlugin plugin = + (MapperPlugin) mProcessor.getMapperPlugins().get( + implname); + + if (plugin == null) { + sendResponse( + ERROR, + new EMapperPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_PLUGIN_NOT_FOUND", + implname)).toString(), + null, resp); + return; + } + + Vector<String> configParams = mProcessor.getMapperDefaultParams(implname); + + IConfigStore destStore = mConfig.getSubStore(mAuth.getId() + ".publish.mapper"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + IConfigStore substore = instancesConfig.makeSubStore(id); + + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + String val = req.getParameter(kv.substring(0, index)); + + if (val == null) { + substore.put(kv.substring(0, index), + kv.substring(index + 1)); + } else { + substore.put(kv.substring(0, index), + val); + } + } + } + substore.put("pluginName", implname); + + // Instantiate an object for this implementation + String className = plugin.getClassPath(); + ILdapMapper mapperInst = null; + + try { + mapperInst = (ILdapMapper) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } + + // initialize the mapper + try { + mapperInst.init(substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } catch (Throwable e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(), null, resp); + return; + } + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // inited and commited ok. now add mapper instance to list. + mProcessor.getMapperInsts().put(id, new MapperProxy(true, mapperInst)); + + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_MAPPER_INST_ADDED", id)); + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_MAPPER_IMPL_NAME, implname); + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void listMapperPlugins(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mProcessor.getMapperPlugins().keys(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + MapperPlugin value = (MapperPlugin) + mProcessor.getMapperPlugins().get(name); + // get Description + String c = value.getClassPath(); + String desc = "unknown"; + + try { + ILdapMapper lp = (ILdapMapper) + Class.forName(c).newInstance(); + + desc = lp.getDescription(); + } catch (Exception exp) { + sendResponse(ERROR, exp.toString(), null, + resp); + return; + } + params.put(name, value.getClassPath() + "," + desc); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + public String getMapperPluginName(ILdapMapper mapper) { + IConfigStore cs = mapper.getConfigStore(); + + try { + return cs.getString("pluginName", ""); + } catch (EBaseException e) { + return ""; + } + } + + private synchronized void listMapperInsts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mProcessor.getMapperInsts().keys(); + + for (; e.hasMoreElements();) { + String name = e.nextElement(); + ILdapMapper value = mProcessor.getMapperInstance(name); + + params.put(name, getMapperPluginName(value) + ";visible"); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void delMapperInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does a`mapper instance exist? + if (mProcessor.getMapperInsts().containsKey(id) == false) { + sendResponse( + ERROR, + new EMapperNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_NOT_FOUND", id)).toString(), + null, resp); + return; + } + + // only remove from memory + // cannot shutdown because we don't keep track of whether it's + // being used. + mProcessor.getMapperInsts().remove(id); + + // remove the configuration. + IConfigStore destStore = + mConfig.getSubStore( + mAuth.getId() + ".publish.mapper"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void delMapperPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + if (mProcessor.getMapperPlugins().containsKey(id) == false) { + sendResponse( + ERROR, + new EMapperPluginNotFound(CMS + .getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_PLUGIN_NOT_FOUND", id)).toString(), + null, resp); + return; + } + + // first check if any instances from this mapper + // DON'T remove mapper if any instance + for (Enumeration<String> e = mProcessor.getMapperInsts().keys(); e.hasMoreElements();) { + String name = (String) e.nextElement(); + ILdapMapper mapper = mProcessor.getMapperInstance(name); + + if (id.equals(getMapperPluginName(mapper))) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_IN_USE"), null, resp); + return; + } + } + + // then delete this mapper + mProcessor.getMapperPlugins().remove((Object) id); + + IConfigStore destStore = + mConfig.getSubStore( + mAuth.getId() + ".publish.mapper"); + IConfigStore instancesConfig = + destStore.getSubStore("impl"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void getMapperConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + + String implname = req.getParameter(Constants.RS_ID); + + if (implname == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + Vector<String> configParams = mProcessor.getMapperDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.put(Constants.PR_MAPPER_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = configParams.elementAt(i); + int index = kv.indexOf('='); + + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + sendResponse(0, null, params, resp); + return; + } + + private synchronized void getMapperInstConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does mapper instance exist? + if (mProcessor.getMapperInsts().containsKey(id) == false) { + sendResponse( + ERROR, + new EMapperNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_NOT_FOUND", id)).toString(), + null, resp); + return; + } + + ILdapMapper mapperInst = (ILdapMapper) + mProcessor.getMapperInstance(id); + Vector<String> configParams = mapperInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_MAPPER_IMPL_NAME, + getMapperPluginName(mapperInst)); + // implName is always required so always send it. + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = configParams.elementAt(i); + int index = kv.indexOf('='); + + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void modMapperInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // Does the manager instance exist? + if (!mProcessor.getMapperInsts().containsKey((Object) id)) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id), + null, resp); + return; + } + + // get new implementation (same or different.) + String implname = req.getParameter(Constants.PR_MAPPER_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp); + return; + } + // get plugin for implementation + MapperPlugin plugin = + (MapperPlugin) mProcessor.getMapperPlugins().get(implname); + + if (plugin == null) { + sendResponse( + ERROR, + new EMapperPluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_MAPPER_PLUGIN_NOT_FOUND", + implname)).toString(), + null, resp); + return; + } + + // save old instance substore params in case new one fails. + + ILdapMapper oldinst = + (ILdapMapper) mProcessor.getMapperInstance(id); + Vector<String> oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.put("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + + saveParams.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + // on to the new instance. + + // remove old substore. + + IConfigStore destStore = + mConfig.getSubStore(mAuth.getId() + + ".publish.mapper"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + + // create new substore. + + Vector<String> configParams = mProcessor.getMapperInstanceParams(id); + + instancesConfig.removeSubStore(id); + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put("pluginName", implname); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = configParams.elementAt(i); + int index = kv.indexOf('='); + String key = kv.substring(0, index); + String val = req.getParameter(key); + + if (val != null) { + substore.put(key, val); + } + } + } + + // Instantiate an object for new implementation + + String className = plugin.getClassPath(); + ILdapMapper newMgrInst = null; + + try { + newMgrInst = (ILdapMapper) + Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } + // initialize the mapper + + try { + newMgrInst.init(substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(getLocale(req)), null, + resp); + return; + } catch (Throwable e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(), null, + resp); + return; + } + + // initialized ok. commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + restore(instancesConfig, id, saveParams); + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // commited ok. replace instance. + + mProcessor.getMapperInsts().put(id, new MapperProxy(true, newMgrInst)); + + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_MAPPER_REPLACED", id)); + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void addRulePlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // is the rule id unique? + if (mProcessor.getRulePlugins().containsKey((Object) id)) { + sendResponse( + ERROR, + new ELdapException(CMS.getUserMessage("CMS_LDAP_SRVLT_ILL_PLUGIN_ID", id)).toString(getLocale(req)), + null, resp); + return; + } + + String classPath = req.getParameter(Constants.PR_RULE_CLASS); + + if (classPath == null) { + sendResponse(ERROR, CMS.getUserMessage("CMS_LDAP_SRVLT_NULL_CLASS"), null, resp); + return; + } + + IConfigStore destStore = null; + + destStore = mConfig.getSubStore( + mAuth.getId() + ".publish.rule"); + IConfigStore instancesConfig = destStore.getSubStore("impl"); + + // Does the class exist? + Class<?> newImpl = null; + + try { + newImpl = Class.forName(classPath); + } catch (ClassNotFoundException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp); + return; + } catch (IllegalArgumentException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp); + return; + } + + // is the class an ILdapRule? + try { + if (ILdapRule.class.isAssignableFrom(newImpl) == false) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, + resp); + return; + } + } catch (NullPointerException e) { // unlikely, only if newImpl null. + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, resp); + return; + } + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(Constants.PR_RULE_CLASS, classPath); + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // add rule to registry. + RulePlugin plugin = new RulePlugin(id, classPath); + + mProcessor.getRulePlugins().put(id, plugin); + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_RULE_PLUG_ADDED", id)); + + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void addRuleInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + if (!isValidID(id)) { + sendResponse(ERROR, "Invalid ID '" + id + "'", + null, resp); + return; + } + + if (mProcessor.getRuleInsts().containsKey((Object) id)) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id), + null, resp); + return; + } + + // get required parameters + String implname = req.getParameter( + Constants.PR_RULE_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp); + return; + } + + // check if implementation exists. + RulePlugin plugin = + (RulePlugin) mProcessor.getRulePlugins().get( + implname); + + if (plugin == null) { + sendResponse( + ERROR, + new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req), + "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", implname)).toString(), + null, resp); + return; + } + + Vector<String> configParams = mProcessor.getRuleDefaultParams(implname); + + IConfigStore destStore = + mConfig.getSubStore(mAuth.getId() + + ".publish.rule"); + IConfigStore instancesConfig = + destStore.getSubStore("instance"); + IConfigStore substore = instancesConfig.makeSubStore(id); + + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = configParams.elementAt(i); + int index = kv.indexOf('='); + String val = req.getParameter(kv.substring(0, index)); + + if (val == null) { + substore.put(kv.substring(0, index), + kv.substring(index + 1)); + } else { + if (val.equals(NOMAPPER)) + val = ""; + substore.put(kv.substring(0, index), + val); + } + } + } + substore.put("pluginName", implname); + + // Instantiate an object for this implementation + String className = plugin.getClassPath(); + ILdapRule ruleInst = null; + + try { + ruleInst = (ILdapRule) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } + + // initialize the rule + try { + ruleInst.init(mProcessor, substore); + ruleInst.setInstanceName(id); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } catch (Throwable e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(), null, resp); + return; + } + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + // inited and commited ok. now add manager instance to list. + mProcessor.getRuleInsts().put(id, ruleInst); + + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_RULE_INST_ADDED", id)); + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_RULE_IMPL_NAME, implname); + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void listRulePlugins(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mProcessor.getRulePlugins().keys(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + RulePlugin value = (RulePlugin) + mProcessor.getRulePlugins().get(name); + // get Description + String c = value.getClassPath(); + String desc = "unknown"; + + try { + ILdapRule lp = (ILdapRule) + Class.forName(c).newInstance(); + + desc = lp.getDescription(); + } catch (Exception exp) { + } + params.put(name, value.getClassPath() + "," + desc); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void listRuleInsts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mProcessor.getRuleInsts().keys(); + + for (; e.hasMoreElements();) { + String name = e.nextElement(); + ILdapRule value = (ILdapRule) + mProcessor.getRuleInsts().get((Object) name); + String enabled = value.enabled() ? "enabled" : "disabled"; + + params.put(name, value.getInstanceName() + ";visible;" + enabled); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + public String getRulePluginName(ILdapRule rule) { + IConfigStore cs = rule.getConfigStore(); + + try { + return cs.getString("pluginName", ""); + } catch (EBaseException e) { + return ""; + } + } + + private synchronized void delRulePlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does rule exist? + if (mProcessor.getRulePlugins().containsKey(id) == false) { + sendResponse(ERROR, + new ERulePluginNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_RULE_PLUGIN_NOT_FOUND", id)) + .toString(), + null, resp); + return; + } + + // first check if any instances from this rule + // DON'T remove rule if any instance + for (Enumeration<ILdapRule> e = mProcessor.getRuleInsts().elements(); e.hasMoreElements();) { + ILdapRule rule = e.nextElement(); + + if (id.equals(getRulePluginName(rule))) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_IN_USE"), null, resp); + return; + } + } + + // then delete this rule + mProcessor.getRulePlugins().remove((Object) id); + + IConfigStore destStore = + mConfig.getSubStore( + mAuth.getId() + ".rule"); + IConfigStore instancesConfig = destStore.getSubStore("impl"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void delRuleInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // prevent deletion of admin and agent. + + // does rule instance exist? + if (mProcessor.getRuleInsts().containsKey(id) == false) { + sendResponse(ERROR, + new ERuleNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_RULE_NOT_FOUND", id)).toString(), + null, resp); + return; + } + + // only remove from memory + // cannot shutdown because we don't keep track of whether it's + // being used. + mProcessor.getRuleInsts().remove(id); + + // remove the configuration. + IConfigStore destStore = + mConfig.getSubStore( + mAuth.getId() + ".publish.rule"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void getRuleConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + String implname = req.getParameter(Constants.RS_ID); + + if (implname == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + Vector<String> configParams = mProcessor.getRuleDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.put(Constants.PR_RULE_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + sendResponse(0, null, params, resp); + return; + } + + private synchronized void getRuleInstConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does rule instance exist? + if (mProcessor.getRuleInsts().containsKey(id) == false) { + sendResponse(ERROR, + new ERuleNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_RULE_NOT_FOUND", id)).toString(), + null, resp); + return; + } + + ILdapRule ruleInst = (ILdapRule) + mProcessor.getRuleInsts().get(id); + Vector<String> configParams = ruleInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_RULE_IMPL_NAME, + getRulePluginName(ruleInst)); + // implName is always required so always send it. + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void modRuleInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // Does the manager instance exist? + if (!mProcessor.getRuleInsts().containsKey((Object) id)) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id), + null, resp); + return; + } + + // get new implementation (same or different.) + String implname = req.getParameter(Constants.PR_RULE_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp); + return; + } + + // get plugin for implementation + RulePlugin plugin = + (RulePlugin) mProcessor.getRulePlugins().get(implname); + + if (plugin == null) { + sendResponse(ERROR, + //new ERulePluginNotFound(implname).toString(getLocale(req)), + "", + null, resp); + return; + } + + // save old instance substore params in case new one fails. + + ILdapRule oldinst = + (ILdapRule) mProcessor.getRuleInsts().get((Object) id); + Vector<String> oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.put("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + + saveParams.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + // on to the new instance. + + // remove old substore. + + IConfigStore destStore = + mConfig.getSubStore( + mAuth.getId() + ".publish.rule"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + + // create new substore. + + Vector<String> configParams = mProcessor.getRuleDefaultParams(implname); + + instancesConfig.removeSubStore(id); + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put("pluginName", implname); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = configParams.elementAt(i); + int index = kv.indexOf('='); + String key = kv.substring(0, index); + String val = req.getParameter(key); + + if (val == null) { + substore.put(key, + kv.substring(index + 1)); + } else { + if (val.equals(NOMAPPER)) + val = ""; + substore.put(key, val); + } + } + } + + // Instantiate an object for new implementation + + String className = plugin.getClassPath(); + ILdapRule newRuleInst = null; + + try { + newRuleInst = (ILdapRule) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } + + // initialize the rule + + try { + newRuleInst.init(mProcessor, substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } catch (Throwable e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(), null, resp); + return; + } + + // initialized ok. commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + restore(instancesConfig, id, saveParams); + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // commited ok. replace instance. + + mProcessor.getRuleInsts().put(id, newRuleInst); + + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_RULE_INST_REP", id)); + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void addPublisherPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // is the manager id unique? + if (mProcessor.getPublisherPlugins().containsKey((Object) id)) { + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_PLUGIN_ID", id)) + .toString(), + null, resp); + return; + } + + String classPath = req.getParameter(Constants.PR_PUBLISHER_CLASS); + + if (classPath == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NULL_CLASS"), null, resp); + return; + } + + IConfigStore destStore = null; + + destStore = mConfig.getSubStore( + mAuth.getId() + ".publish.publisher"); + IConfigStore instancesConfig = destStore.getSubStore("impl"); + + // Does the class exist? + Class<?> newImpl = null; + + try { + newImpl = Class.forName(classPath); + } catch (ClassNotFoundException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp); + return; + } catch (IllegalArgumentException e) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_NO_CLASS"), null, resp); + return; + } + + // is the class an ILdapPublisher? + try { + if (ILdapPublisher.class.isAssignableFrom(newImpl) == false) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, + resp); + return; + } + } catch (NullPointerException e) { // unlikely, only if newImpl null. + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_CLASS", classPath), null, resp); + return; + } + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put(Constants.PR_PUBLISHER_CLASS, classPath); + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // add publisher to registry. + PublisherPlugin plugin = new PublisherPlugin(id, classPath); + + mProcessor.getPublisherPlugins().put(id, plugin); + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_PUB_PLUG_ADDED", id)); + + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void addPublisherInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + if (!isValidID(id)) { + sendResponse(ERROR, "Invalid ID '" + id + "'", + null, resp); + return; + } + + if (mProcessor.getPublisherInsts().containsKey((Object) id)) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id), + null, resp); + return; + } + + // get required parameters + String implname = req.getParameter( + Constants.PR_PUBLISHER_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp); + return; + } + + // check if implementation exists. + PublisherPlugin plugin = + (PublisherPlugin) mProcessor.getPublisherPlugins().get( + implname); + + if (plugin == null) { + sendResponse( + ERROR, + new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req), + "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", implname)).toString(), + null, resp); + return; + } + + Vector<String> configParams = mProcessor.getPublisherDefaultParams(implname); + + IConfigStore destStore = + mConfig.getSubStore(mAuth.getId() + ".publish.publisher"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + IConfigStore substore = instancesConfig.makeSubStore(id); + + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = configParams.elementAt(i); + int index = kv.indexOf('='); + String val = null; + + if (index == -1) { + val = req.getParameter(kv); + } else { + val = req.getParameter(kv.substring(0, index)); + } + if (val == null) { + if (index == -1) { + substore.put(kv, ""); + } else { + substore.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } else { + if (index == -1) { + substore.put(kv, val); + } else { + substore.put(kv.substring(0, index), + val); + } + } + } + } + substore.put("pluginName", implname); + + // Instantiate an object for this implementation + String className = plugin.getClassPath(); + ILdapPublisher publisherInst = null; + + try { + publisherInst = (ILdapPublisher) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } + + // initialize the publisher + try { + publisherInst.init(substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } catch (Throwable e) { + instancesConfig.removeSubStore(id); + sendResponse(ERROR, e.toString(), null, resp); + return; + } + + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + instancesConfig.removeSubStore(id); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // inited and commited ok. now add manager instance to list. + mProcessor.getPublisherInsts().put(id, new PublisherProxy(true, publisherInst)); + + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_PUB_INST_ADDED", id)); + + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_PUBLISHER_IMPL_NAME, implname); + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void listPublisherPlugins(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mProcessor.getPublisherPlugins().keys(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + PublisherPlugin value = (PublisherPlugin) + mProcessor.getPublisherPlugins().get(name); + // get Description + String c = value.getClassPath(); + String desc = "unknown"; + + try { + ILdapPublisher lp = (ILdapPublisher) + Class.forName(c).newInstance(); + + desc = lp.getDescription(); + } catch (Exception exp) { + } + params.put(name, value.getClassPath() + "," + desc); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + public String getPublisherPluginName(ILdapPublisher pub) { + IConfigStore cs = pub.getConfigStore(); + + try { + return cs.getString("pluginName", ""); + } catch (EBaseException e) { + return ""; + } + } + + private synchronized void listPublisherInsts(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + Enumeration<String> e = mProcessor.getPublisherInsts().keys(); + + for (; e.hasMoreElements();) { + String name = e.nextElement(); + ILdapPublisher value = mProcessor.getPublisherInstance(name); + + if (value == null) + continue; + params.put(name, getPublisherPluginName(value) + ";visible"); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void delPublisherPlugin(HttpServletRequest req, + HttpServletResponse resp, String scope) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does publisher exist? + if (mProcessor.getPublisherPlugins().containsKey(id) == false) { + sendResponse( + ERROR, + new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req), + "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", id)).toString(), + null, resp); + return; + } + + // first check if any instances from this publisher + // DON'T remove publisher if any instance + for (Enumeration<String> e = mProcessor.getPublisherInsts().keys(); e.hasMoreElements();) { + String name = e.nextElement(); + ILdapPublisher publisher = + mProcessor.getPublisherInstance(name); + + if (id.equals(getPublisherPluginName(publisher))) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_IN_USE"), null, resp); + return; + } + } + + // then delete this publisher + mProcessor.getPublisherPlugins().remove((Object) id); + + IConfigStore destStore = + mConfig.getSubStore(mAuth.getId() + ".publish.publisher"); + IConfigStore instancesConfig = destStore.getSubStore("impl"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + private synchronized void delPublisherInst(HttpServletRequest req, + HttpServletResponse resp, String scope) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // prevent deletion of admin and agent. + + // does publisher instance exist? + if (mProcessor.getPublisherInsts().containsKey(id) == false) { + sendResponse(ERROR, + new EPublisherNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_PUBLISHER_NOT_FOUND", id)) + .toString(), + null, resp); + return; + } + + // only remove from memory + // cannot shutdown because we don't keep track of whether it's + // being used. + mProcessor.getPublisherInsts().remove(id); + + // remove the configuration. + IConfigStore destStore = + mConfig.getSubStore(mAuth.getId() + ".publish.publisher"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + + instancesConfig.removeSubStore(id); + // commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * used for getting the required configuration parameters (with + * possible default values) for a particular plugin + * implementation name specified in the RS_ID. Actually, there is + * no logic in here to set any default value here...there's no + * default value for any parameter in this publishing subsystem + * at this point. Later, if we do have one (or some), it can be + * added. The interface remains the same. + */ + private synchronized void getConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException, EBaseException { + + String implname = req.getParameter(Constants.RS_ID); + + if (implname == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + Vector<String> configParams = mProcessor.getPublisherDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.put(Constants.PR_PUBLISHER_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + if (index == -1) { + params.put(kv, ""); + } else { + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + } + sendResponse(0, null, params, resp); + return; + } + + private synchronized void getInstConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // does publisher instance exist? + if (mProcessor.getPublisherInsts().containsKey(id) == false) { + sendResponse(ERROR, + new EPublisherNotFound(CMS.getUserMessage(getLocale(req), "CMS_LDAP_PUBLISHER_NOT_FOUND", id)) + .toString(), + null, resp); + return; + } + + ILdapPublisher publisherInst = (ILdapPublisher) + mProcessor.getPublisherInstance(id); + Vector<String> configParams = publisherInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_PUBLISHER_IMPL_NAME, + getPublisherPluginName(publisherInst)); + // implName is always required so always send it. + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + params.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * Modify publisher instance. + * This will actually create a new instance with new configuration + * parameters and replace the old instance, if the new instance + * created and initialized successfully. + * The old instance is left running. so this is very expensive. + * Restart of server recommended. + */ + private synchronized void modPublisherInst(HttpServletRequest req, + HttpServletResponse resp, String scope) + throws ServletException, IOException, EBaseException { + + // expensive operation. + + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + //System.out.println("SRVLT_NULL_RS_ID"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // Does the manager instance exist? + if (!mProcessor.getPublisherInsts().containsKey((Object) id)) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ILL_INST_ID", id), + null, resp); + return; + } + + // get new implementation (same or different.) + String implname = req.getParameter(Constants.PR_PUBLISHER_IMPL_NAME); + + if (implname == null) { + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_LDAP_SRVLT_ADD_MISSING_PARAMS"), null, resp); + return; + } + + // get plugin for implementation + PublisherPlugin plugin = + (PublisherPlugin) mProcessor.getPublisherPlugins().get(implname); + + if (plugin == null) { + sendResponse( + ERROR, + new EPublisherPluginNotFound(CMS.getUserMessage(getLocale(req), + "CMS_LDAP_PUBLISHER_PLUGIN_NOT_FOUND", implname)).toString(), + null, resp); + return; + } + + // save old instance substore params in case new one fails. + + ILdapPublisher oldinst = mProcessor.getPublisherInstance(id); + Vector<String> oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + String pubType = ""; + + // implName is always required so always include it it. + saveParams.put("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = (String) oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + if (index > -1) { + if (kv.substring(0, index).equalsIgnoreCase("caObjectClass")) { + pubType = "cacert"; + } else if (kv.substring(0, index).equalsIgnoreCase("crlObjectClass")) { + pubType = "crl"; + } + + saveParams.put(kv.substring(0, index), + kv.substring(index + 1)); + } + } + } + + // on to the new instance. + + // remove old substore. + + IConfigStore destStore = + mConfig.getSubStore(mAuth.getId() + ".publish.publisher"); + IConfigStore instancesConfig = destStore.getSubStore("instance"); + + // get objects added and deleted + if (pubType.equals("cacert")) { + saveParams.put("caObjectClassAdded", instancesConfig.getString(id + ".caObjectClassAdded", "")); + saveParams.put("caObjectClassDeleted", instancesConfig.getString(id + ".caObjectClassDeleted", "")); + } else if (pubType.equals("crl")) { + saveParams.put("crlObjectClassAdded", instancesConfig.getString(id + ".crlObjectClassAdded", "")); + saveParams.put("crlObjectClassDeleted", instancesConfig.getString(id + ".crlObjectClassDeleted", "")); + } + + // create new substore. + + Vector<String> configParams = mProcessor.getPublisherInstanceParams(id); + + instancesConfig.removeSubStore(id); + + IConfigStore substore = instancesConfig.makeSubStore(id); + + substore.put("pluginName", implname); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + String key = kv.substring(0, index); + String val = req.getParameter(key); + + if (val != null) { + substore.put(key, val); + } + } + } + + // process any changes to the ldap object class definitions + if (pubType.equals("cacert")) { + processChangedOC(saveParams, substore, "caObjectClass"); + substore.put("pubtype", "cacert"); + } + + if (pubType.equals("crl")) { + processChangedOC(saveParams, substore, "crlObjectClass"); + substore.put("pubtype", "crl"); + } + + // Instantiate an object for new implementation + + String className = plugin.getClassPath(); + ILdapPublisher newMgrInst = null; + + try { + newMgrInst = (ILdapPublisher) Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + // cleanup + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (InstantiationException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } catch (IllegalAccessException e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, + new ELdapException(CMS.getUserMessage(getLocale(req), "CMS_LDAP_FAIL_LOAD_CLASS", className)) + .toString(), + null, resp); + return; + } + + // initialize the publisher + + try { + newMgrInst.init(substore); + } catch (EBaseException e) { + // don't commit in this case and cleanup the new substore. + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(getLocale(req)), null, resp); + return; + } catch (Throwable e) { + restore(instancesConfig, id, saveParams); + sendResponse(ERROR, e.toString(), null, resp); + return; + } + + // initialized ok. commiting + try { + mConfig.commit(true); + } catch (EBaseException e) { + // clean up. + restore(instancesConfig, id, saveParams); + //System.out.println("SRVLT_FAIL_COMMIT"); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_COMMIT_FAILED"), + null, resp); + return; + } + + // commited ok. replace instance. + + mProcessor.getPublisherInsts().put(id, new PublisherProxy(true, newMgrInst)); + + mProcessor.log(ILogger.LL_INFO, + CMS.getLogMessage("ADMIN_SRVLT_PUB_INST_REP", id)); + + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + // convenience function - takes list1, list2. Returns what is in list1 + // but not in list2 + private String[] getExtras(String[] list1, String[] list2) { + Vector<String> extras = new Vector<String>(); + for (int i = 0; i < list1.length; i++) { + boolean match = false; + for (int j = 0; j < list2.length; j++) { + if ((list1[i].trim()).equalsIgnoreCase(list2[j].trim())) { + match = true; + break; + } + } + if (!match) + extras.add(list1[i].trim()); + } + + return (String[]) extras.toArray(new String[extras.size()]); + } + + // convenience function - takes list1, list2. Concatenates the two + // lists removing duplicates + private String[] joinLists(String[] list1, String[] list2) { + Vector<String> sum = new Vector<String>(); + for (int i = 0; i < list1.length; i++) { + sum.add(list1[i]); + } + + for (int i = 0; i < list2.length; i++) { + boolean match = false; + for (int j = 0; j < list1.length; j++) { + if ((list2[i].trim()).equalsIgnoreCase(list1[j].trim())) { + match = true; + break; + } + } + if (!match) + sum.add(list2[i].trim()); + } + + return (String[]) sum.toArray(new String[sum.size()]); + } + + // convenience funtion. Takes a string array and delimiter + // and returns a String with the concatenation + private static String join(String[] s, String delimiter) { + if (s.length == 0) + return ""; + + StringBuffer buffer = new StringBuffer(s[0]); + if (s.length > 1) { + for (int i = 1; i < s.length; i++) { + buffer.append(delimiter).append(s[i].trim()); + } + } + return buffer.toString(); + } + + private void processChangedOC(NameValuePairs saveParams, IConfigStore newstore, String objName) { + String newOC = null, oldOC = null; + String oldAdded = null, oldDeleted = null; + + try { + newOC = newstore.getString(objName); + } catch (Exception e) { + } + + oldOC = saveParams.get(objName); + oldAdded = saveParams.get(objName + "Added"); + oldDeleted = saveParams.get(objName + "Deleted"); + + if ((oldOC == null) || (newOC == null)) + return; + if (oldOC.equalsIgnoreCase(newOC)) + return; + + String[] oldList = oldOC.split(","); + String[] newList = newOC.split(","); + String[] deletedList = getExtras(oldList, newList); + String[] addedList = getExtras(newList, oldList); + + // CMS.debug("addedList = " + join(addedList, ",")); + // CMS.debug("deletedList = " + join(deletedList, ",")); + + if ((addedList.length == 0) && (deletedList.length == 0)) + return; // no changes + + if (oldAdded != null) { + // CMS.debug("oldAdded is " + oldAdded); + String[] oldAddedList = oldAdded.split(","); + addedList = joinLists(addedList, oldAddedList); + } + + if (oldDeleted != null) { + // CMS.debug("oldDeleted is " + oldDeleted); + String[] oldDeletedList = oldDeleted.split(","); + deletedList = joinLists(deletedList, oldDeletedList); + } + + String[] addedList1 = getExtras(addedList, deletedList); + String[] deletedList1 = getExtras(deletedList, addedList); + + //create the final strings and write to config + String addedListStr = join(addedList1, ","); + String deletedListStr = join(deletedList1, ","); + + CMS.debug("processChangedOC: added list is " + addedListStr); + CMS.debug("processChangedOC: deleted list is " + deletedListStr); + + newstore.put(objName + "Added", addedListStr); + newstore.put(objName + "Deleted", deletedListStr); + } + + // convenience routine. + private static void restore(IConfigStore store, + String id, NameValuePairs saveParams) { + store.removeSubStore(id); + IConfigStore rstore = store.makeSubStore(id); + + for (String key : saveParams.keySet()) { + String value = saveParams.get(key); + + if (value != null) + rstore.put(key, value); + } + } + + private String dashes(int len) { + String dashes = "..................................................."; + + if (len <= 0) + return ""; + String new1 = dashes.substring(0, len); + + return new1; + } + + /** + * logs an entry in the log file. + */ + public void log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, + ILogger.S_LDAP, level, "PublishingAdminServlet: " + msg); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/RAAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/RAAdminServlet.java new file mode 100644 index 000000000..5bdb14177 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/RAAdminServlet.java @@ -0,0 +1,584 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequestListener; + +/** + * A class representings an administration servlet for Registration + * Authority. This servlet is responsible to serve RA + * administrative operations such as configuration parameter + * updates. + * + * @version $Revision$, $Date$ + */ +public class RAAdminServlet extends AdminServlet { + /** + * + */ + private static final long serialVersionUID = 8417319111438832435L; + + protected static final String PROP_ENABLED = "enabled"; + + /*========================================================== + * variables + *==========================================================*/ + private final static String INFO = "RAAdminServlet"; + private IRegistrationAuthority mRA = null; + + /*========================================================== + * constructors + *==========================================================*/ + + /** + * Constructs RA servlet. + */ + public RAAdminServlet() { + super(); + } + + /*========================================================== + * public methods + *==========================================================*/ + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mRA = (IRegistrationAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_RA); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP request. Each request is authenticated to + * the authenticate manager. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + //get all operational flags + String op = req.getParameter(Constants.OP_TYPE); + String scope = req.getParameter(Constants.OP_SCOPE); + + //check operational flags + if ((op == null) || (scope == null)) { + sendResponse(1, "Invalid Protocol", null, resp); + return; + } + + //authenticate the user + super.authenticate(req); + + //perform services + try { + AUTHZ_RES_NAME = "certServer.ra.configuration"; + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GENERAL)) { + readGeneralConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_CONNECTOR)) { + getConnectorConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP)) { + getNotificationReqCompConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP)) { + getNotificationRevCompConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) { + getNotificationRIQConfig(req, resp); + return; + } else { + sendResponse(1, "Unknown operation", null, resp); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GENERAL)) { + modifyGeneralConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_CONNECTOR)) { + setConnectorConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REQ_COMP)) { + setNotificationReqCompConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_REV_COMP)) { + setNotificationRevCompConfig(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_NOTIFICATION_RIQ)) { + setNotificationRIQConfig(req, resp); + return; + } else { + sendResponse(1, "Unknown operation", null, resp); + return; + } + } + } catch (Exception e) { + //System.out.println("XXX >>>" + e.toString() + "<<<"); + sendResponse(1, "Unknown operation", null, resp); + } + + return; + } + + /*========================================================== + * private methods + *==========================================================*/ + + /* + * handle getting completion (cert issued) notification config info + */ + private void getNotificationCompConfig(HttpServletRequest req, + HttpServletResponse resp, IConfigStore rc) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + params.put(name, rc.getString(name, "")); + } + + params.put(Constants.PR_ENABLE, + rc.getString(PROP_ENABLED, Constants.FALSE)); + //System.out.println("Send: "+params.toString()); + sendResponse(SUCCESS, null, params, resp); + } + + private void getNotificationReqCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore config = mRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_ISSUED_SUBSTORE); + + getNotificationCompConfig(req, resp, rc); + + } + + private void getNotificationRevCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore config = mRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_REVOKED_SUBSTORE); + + getNotificationCompConfig(req, resp, rc); + + } + + /* + * handle getting request in queue notification config info + */ + private void getNotificationRIQConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + IConfigStore config = mRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(IRegistrationAuthority.PROP_REQ_IN_Q_SUBSTORE); + + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + params.put(name, riq.getString(name, "")); + } + + params.put(Constants.PR_ENABLE, + riq.getString(PROP_ENABLED, Constants.FALSE)); + //System.out.println("Send: "+params.toString()); + sendResponse(SUCCESS, null, params, resp); + } + + /* + * handle setting request in queue notification config info + */ + private void setNotificationRIQConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore config = mRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(IRegistrationAuthority.PROP_REQ_IN_Q_SUBSTORE); + + //set rest of the parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + String val = req.getParameter(name); + + riq.putString(name, val); + mRA.getRequestInQListener().set(name, val); + } + + // set enable flag + String enabledString = req.getParameter(Constants.PR_ENABLE); + + riq.putString(PROP_ENABLED, enabledString); + mRA.getRequestInQListener().set(PROP_ENABLED, enabledString); + + commit(true); + + sendResponse(SUCCESS, null, null, resp); + } + + /* + * handle setting request complete notification config info + */ + private void setNotificationCompConfig(HttpServletRequest req, + HttpServletResponse resp, IConfigStore rc, IRequestListener thisListener) throws ServletException, + IOException, EBaseException { + //set rest of the parameters + @SuppressWarnings("unchecked") + Enumeration<String> e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = e.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.PR_ENABLE)) + continue; + String val = req.getParameter(name); + + rc.putString(name, val); + thisListener.set(name, val); + } + + // set enable flag + String enabledString = req.getParameter(Constants.PR_ENABLE); + + rc.putString(PROP_ENABLED, enabledString); + thisListener.set(PROP_ENABLED, enabledString); + + commit(true); + + sendResponse(SUCCESS, null, null, resp); + } + + private void setNotificationReqCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore config = mRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_ISSUED_SUBSTORE); + + setNotificationCompConfig(req, resp, rc, mRA.getCertIssuedListener()); + + } + + private void setNotificationRevCompConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore config = mRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(IRegistrationAuthority.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(IRegistrationAuthority.PROP_CERT_REVOKED_SUBSTORE); + + setNotificationCompConfig(req, resp, rc, mRA.getCertRevokedListener()); + } + + private void getConnectorConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + IConfigStore raConfig = mRA.getConfigStore(); + IConfigStore connectorConfig = raConfig.getSubStore("connector"); + IConfigStore caConnectorConfig = null; + + if (isCAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("CA"); + } else if (isRAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("RA"); + } else if (isKRAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("KRA"); + } + + /* + Enumeration enum = req.getParameterNames(); + NameValuePairs params = new NameValuePairs(); + while (enum.hasMoreElements()) { + String key = (String)enum.nextElement(); + if (key.equals("RS_ID")) { + String val = req.getParameter(key); + if (val.equals("CA Connector")) + } + } + */ + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + NameValuePairs params = new NameValuePairs(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = enum1.nextElement(); + + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.OP_TYPE)) + continue; + + params.put(name, caConnectorConfig.getString(name, "")); + } + } + sendResponse(SUCCESS, null, params, resp); + } + + private void setConnectorConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore raConfig = mRA.getConfigStore(); + IConfigStore connectorConfig = raConfig.getSubStore("connector"); + IConfigStore caConnectorConfig = null; + // String nickname = raConfig.getString("certNickname", ""); + + if (isCAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("CA"); + } else if (isRAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("RA"); + } else if (isKRAConnector(req)) { + caConnectorConfig = connectorConfig.getSubStore("KRA"); + } + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = enum1.nextElement(); + + if (name.equals(Constants.OP_TYPE)) + continue; + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + /* + if (name.equals("nickName")) { + caConnectorConfig.putString(name, nickname); + continue; + } + */ + caConnectorConfig.putString(name, req.getParameter(name)); + } + } + + commit(true); + sendResponse(RESTART, null, null, resp); + } + + private boolean isCAConnector(HttpServletRequest req) { + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + + if (key.equals("RS_ID")) { + String val = req.getParameter(key); + + if (val.equals("Certificate Manager Connector")) + return true; + else + return false; + } + } + return false; + } + + private boolean isRAConnector(HttpServletRequest req) { + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + + if (key.equals("RS_ID")) { + String val = req.getParameter(key); + + if (val.equals("Registration Manager Connector")) + return true; + else + return false; + } + } + return false; + } + + private boolean isKRAConnector(HttpServletRequest req) { + + @SuppressWarnings("unchecked") + Enumeration<String> enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = enum1.nextElement(); + + if (key.equals("RS_ID")) { + String val = req.getParameter(key); + + if (val.equals("Data Recovery Manager Connector")) + return true; + else + return false; + } + } + return false; + } + + //reading the RA general information + private void readGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + /* + ISubsystem eeGateway = + SubsystemRegistry.getInstance().get("eeGateway"); + String value = "false"; + if (eeGateway != null) { + IConfigStore eeConfig = eeGateway.getConfigStore(); + if (eeConfig != null) + value = eeConfig.getString("enabled", "true"); + } + params.add(Constants.PR_EE_ENABLED, value); + */ + + sendResponse(SUCCESS, null, params, resp); + } + + //mdify RA General Information + private void modifyGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + /* + ISubsystem eeGateway = + SubsystemRegistry.getInstance().get("eeGateway"); + IConfigStore eeConfig = null; + if (eeGateway != null) + eeConfig = eeGateway.getConfigStore(); + + Enumeration enum = req.getParameterNames(); + while (enum.hasMoreElements()) { + String key = (String)enum.nextElement(); + if (key.equals(Constants.PR_EE_ENABLED)) { + if (eeConfig != null) + eeConfig.putString("enabled", + req.getParameter(Constants.PR_EE_ENABLED)); + } + } + + */ + sendResponse(RESTART, null, null, resp); + commit(true); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java new file mode 100644 index 000000000..4bebe85d3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java @@ -0,0 +1,373 @@ +// --- 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.admin; + +import java.io.IOException; +import java.util.Enumeration; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.property.IConfigTemplate; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.registry.IPluginInfo; +import com.netscape.certsrv.registry.IPluginRegistry; + +/** + * This implements the administration servlet for registry subsystem. + * + * @version $Revision$, $Date$ + */ +public class RegistryAdminServlet extends AdminServlet { + /** + * + */ + private static final long serialVersionUID = 2104924641665675578L; + + public final static String PROP_AUTHORITY = "authority"; + + private final static String INFO = "RegistryAdminServlet"; + private final static String PW_PASSWORD_CACHE_ADD = + "PASSWORD_CACHE_ADD"; + + public final static String PROP_PREDICATE = "predicate"; + private IAuthority mAuthority = null; + private IPluginRegistry mRegistry = null; + + // These will be moved to PolicyResources + public static String INVALID_POLICY_SCOPE = "Invalid policy administration scope"; + public static String INVALID_POLICY_IMPL_OP = "Invalid operation for policy implementation management"; + public static String NYI = "Not Yet Implemented"; + public static String INVALID_POLICY_IMPL_CONFIG = "Invalid policy implementation configuration"; + public static String INVALID_POLICY_INSTANCE_CONFIG = "Invalid policy instance configuration"; + public static String MISSING_POLICY_IMPL_ID = "Missing policy impl id in request"; + public static String MISSING_POLICY_IMPL_CLASS = "Missing policy impl class in request"; + public static String INVALID_POLICY_IMPL_ID = "Invalid policy impl id in request"; + public static String MISSING_POLICY_INST_ID = "Missing policy impl id in request"; + public static String INVALID_POLICY_INST_ID = "Invalid policy impl id in request"; + public static String COMMA = ","; + public static String MISSING_POLICY_ORDERING = "Missing policy ordering"; + + /** + * Constructs administration servlet. + */ + public RegistryAdminServlet() { + super(); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + String authority = config.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) CMS.getSubsystem(authority); + mRegistry = (IPluginRegistry) CMS.getSubsystem(CMS.SUBSYSTEM_REGISTRY); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP admin request. + */ + public void service(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + super.authenticate(req); + + AUTHZ_RES_NAME = "certServer.registry.configuration"; + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + if (scope.equals(ScopeDef.SC_SUPPORTED_CONSTRAINTPOLICIES)) { + if (op.equals(OpDef.OP_READ)) + if (!readAuthorize(req, resp)) + return; + getSupportedConstraintPolicies(req, resp); + } else { + processImplMgmt(req, resp); + } + } + + private boolean readAuthorize(HttpServletRequest req, + HttpServletResponse resp) throws IOException { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return false; + } + return true; + } + + private boolean modifyAuthorize(HttpServletRequest req, + HttpServletResponse resp) throws IOException { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return false; + } + return true; + } + + /** + * Process Policy Implementation Management. + */ + public void processImplMgmt(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + // Get operation type + String op = req.getParameter(Constants.OP_TYPE); + + if (op.equals(OpDef.OP_SEARCH)) { + if (!readAuthorize(req, resp)) + return; + listImpls(req, resp); + } else if (op.equals(OpDef.OP_READ)) { + if (!readAuthorize(req, resp)) + return; + getProfileImplConfig(req, resp); + } else if (op.equals(OpDef.OP_DELETE)) { + if (!modifyAuthorize(req, resp)) + return; + deleteImpl(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + if (!modifyAuthorize(req, resp)) + return; + addImpl(req, resp); + } else + sendResponse(ERROR, INVALID_POLICY_IMPL_OP, + null, resp); + } + + public void addImpl(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + // Get the policy impl id. + String id = req.getParameter(Constants.RS_ID); + String scope = req.getParameter(Constants.OP_SCOPE); + String classPath = req.getParameter(Constants.PR_POLICY_CLASS); + String desc = req.getParameter(Constants.PR_POLICY_DESC); + + if (id == null) { + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + IPluginInfo info = mRegistry.createPluginInfo(id, desc, classPath); + try { + mRegistry.addPluginInfo(scope, id, info); + } catch (Exception e) { + CMS.debug(e.toString()); + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + public void deleteImpl(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + // Get the policy impl id. + String id = req.getParameter(Constants.RS_ID); + String scope = req.getParameter(Constants.OP_SCOPE); + + if (id == null) { + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + IPluginInfo info = mRegistry.getPluginInfo(scope, id); + + if (info == null) { + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + try { + mRegistry.removePluginInfo(scope, id); + } catch (Exception e) { + CMS.debug(e.toString()); + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + /** + * Lists all registered profile impementations + */ + public void listImpls(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + String scope = req.getParameter(Constants.OP_SCOPE); + Enumeration<String> impls = mRegistry.getIds(scope); + NameValuePairs nvp = new NameValuePairs(); + + while (impls.hasMoreElements()) { + String id = impls.nextElement(); + IPluginInfo info = mRegistry.getPluginInfo(scope, id); + + nvp.put(id, info.getClassName() + "," + + info.getDescription(getLocale(req)) + "," + info.getName(getLocale(req))); + } + + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getSupportedConstraintPolicies(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException { + String id = req.getParameter(Constants.RS_ID); + + if (id == null) { + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + try { + IPluginInfo info = mRegistry.getPluginInfo("defaultPolicy", id); + String className = info.getClassName(); + IPolicyDefault policyDefaultClass = (IPolicyDefault) + Class.forName(className).newInstance(); + + if (policyDefaultClass != null) { + Enumeration<String> impls = mRegistry.getIds("constraintPolicy"); + + while (impls.hasMoreElements()) { + String constraintID = (String) impls.nextElement(); + IPluginInfo constraintInfo = mRegistry.getPluginInfo( + "constraintPolicy", constraintID); + IPolicyConstraint policyConstraintClass = (IPolicyConstraint) + Class.forName(constraintInfo.getClassName()).newInstance(); + + CMS.debug("RegistryAdminServlet: getSUpportedConstraint " + constraintInfo.getClassName()); + + if (policyConstraintClass.isApplicable(policyDefaultClass)) { + CMS.debug("RegistryAdminServlet: getSUpportedConstraint isApplicable " + + constraintInfo.getClassName()); + nvp.put(constraintID, + constraintInfo.getClassName() + + "," + + constraintInfo.getDescription(getLocale(req)) + "," + + constraintInfo.getName(getLocale(req))); + } + } + } + } catch (Exception ex) { + CMS.debug("RegistyAdminServlet: getSupportConstraintPolicies: " + ex.toString()); + CMS.debug(ex); + } + sendResponse(SUCCESS, null, nvp, resp); + } + + public void getProfileImplConfig(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + + // Get the policy impl id. + String id = req.getParameter(Constants.RS_ID); + String scope = req.getParameter(Constants.OP_SCOPE); + + if (id == null) { + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + IPluginInfo info = mRegistry.getPluginInfo(scope, id); + + if (info == null) { + sendResponse(ERROR, MISSING_POLICY_IMPL_ID, null, resp); + return; + } + + NameValuePairs nvp = new NameValuePairs(); + + String className = info.getClassName(); + IConfigTemplate template = null; + + try { + template = (IConfigTemplate) + Class.forName(className).newInstance(); + } catch (Exception e) { + } + if (template != null) { + Enumeration<String> names = template.getConfigNames(); + + if (names != null) { + while (names.hasMoreElements()) { + String name = names.nextElement(); + CMS.debug("RegistryAdminServlet: getProfileImpl descriptor " + name); + IDescriptor desc = template.getConfigDescriptor(getLocale(req), name); + + if (desc != null) { + try { + String value = + getNonNull(desc.getSyntax()) + + ";" + getNonNull(desc.getConstraint()) + ";" + + desc.getDescription(getLocale(req)) + ";" + + getNonNull(desc.getDefaultValue()); + + CMS.debug("RegistryAdminServlet: getProfileImpl " + value); + nvp.put(name, value); + } catch (Exception e) { + + CMS.debug("RegistryAdminServlet: getProfileImpl skipped descriptor for " + name); + } + } else { + CMS.debug("RegistryAdminServlet: getProfileImpl cannot find descriptor for " + name); + } + } + } + } + sendResponse(SUCCESS, null, nvp, resp); + } + + protected String getNonNull(String s) { + if (s == null) + return ""; + return s; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/SystemCertificateResource.java b/base/common/src/com/netscape/cms/servlet/admin/SystemCertificateResource.java new file mode 100644 index 000000000..d4cfcd296 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/SystemCertificateResource.java @@ -0,0 +1,25 @@ +package com.netscape.cms.servlet.admin; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.jboss.resteasy.annotations.ClientResponseType; + +import com.netscape.cms.servlet.cert.model.CertificateData; + +@Path("/config/cert") +public interface SystemCertificateResource { + + /** + * Used to retrieve the transport certificate + */ + @GET + @Path("/transport") + @ClientResponseType(entityType=CertificateData.class) + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + public Response getTransportCert(); + +}
\ No newline at end of file diff --git a/base/common/src/com/netscape/cms/servlet/admin/SystemCertificateResourceService.java b/base/common/src/com/netscape/cms/servlet/admin/SystemCertificateResourceService.java new file mode 100644 index 000000000..48f410c73 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/SystemCertificateResourceService.java @@ -0,0 +1,80 @@ +// --- 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) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.admin; + +import java.security.cert.CertificateEncodingException; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.security.ITransportKeyUnit; +import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.cert.model.CertificateData; + +/** + * This is the class used to list, retrieve and modify system certificates for all Java subsystems. + * + * @author alee + * + */ +public class SystemCertificateResourceService extends CMSResourceService implements SystemCertificateResource { + + @Context + Request request; + + /** + * Used to retrieve the transport certificate + */ + public Response getTransportCert() { + CertificateData cert = null; + IKeyRecoveryAuthority kra = null; + + // auth and authz + + kra = (IKeyRecoveryAuthority) CMS.getSubsystem("kra"); + if (kra == null) { + // no KRA + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + + ITransportKeyUnit tu = kra.getTransportKeyUnit(); + if (tu == null) { + CMS.debug("getTransportCert: transport key unit is null"); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + org.mozilla.jss.crypto.X509Certificate transportCert = tu.getCertificate(); + if (transportCert == null) { + CMS.debug("getTransportCert: transport cert is null"); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + try { + cert = createCertificateData(transportCert); + } catch (CertificateEncodingException e) { + CMS.debug("getTransportCert: certificate encoding exception with transport cert"); + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return sendConditionalGetResponse(DEFAULT_LONG_CACHE_LIFETIME, cert, request); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java b/base/common/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java new file mode 100644 index 000000000..e5a6dd3c4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java @@ -0,0 +1,2313 @@ +// --- 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.admin; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPException; +import netscape.security.pkcs.PKCS7; +import netscape.security.x509.X509CertImpl; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.InternalCertificate; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.ICertPrettyPrint; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.common.NameValuePairs; +import com.netscape.certsrv.common.OpDef; +import com.netscape.certsrv.common.ScopeDef; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.password.IPasswordCheck; +import com.netscape.certsrv.usrgrp.EUsrGrpException; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cmsutil.util.Cert; +import com.netscape.cmsutil.util.Utils; + +/** + * A class representing an administration servlet for + * User/Group Manager. It communicates with client + * SDK to allow remote administration of User/Group + * manager. + * + * This servlet will be registered to remote + * administration subsystem by usrgrp manager. + * + * @version $Revision$, $Date$ + */ +public class UsrGrpAdminServlet extends AdminServlet { + + /** + * + */ + private static final long serialVersionUID = -4341817607402387714L; + private final static String INFO = "UsrGrpAdminServlet"; + private final static String RES_CA_GROUP = "certServer.ca.group"; + private final static String RES_RA_GROUP = "certServer.ra.group"; + private final static String RES_KRA_GROUP = "certServer.kra.group"; + private final static String RES_OCSP_GROUP = "certServer.ocsp.group"; + private final static String RES_TKS_GROUP = "certServer.tks.group"; + private final static String SYSTEM_USER = "$System$"; + // private final static String RES_GROUP = "root.common.goldfish"; + + private final static String BACK_SLASH = "\\"; + + private final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE = + "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3"; + + private IUGSubsystem mMgr = null; + + private static String[] mMultiRoleGroupEnforceList = null; + private final static String MULTI_ROLE_ENABLE = "multiroles.enable"; + private final static String MULTI_ROLE_ENFORCE_GROUP_LIST = "multiroles.false.groupEnforceList"; + + /** + * Constructs User/Group manager servlet. + */ + public UsrGrpAdminServlet() { + super(); + mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + } + + /** + * Initializes this servlet. + */ + public void init(ServletConfig config) throws ServletException { + super.init(config); + mMgr = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves incoming User/Group management request. + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + String scope = super.getParameter(req, Constants.OP_SCOPE); + String op = super.getParameter(req, Constants.OP_TYPE); + + if (op == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_INVALID_PROTOCOL")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_PROTOCOL"), + null, resp); + return; + } + + Locale clientLocale = super.getLocale(req); + + try { + super.authenticate(req); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS")); + + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHS_FAILED"), + null, resp); + return; + } + + // authorization + // temporary test before servlets are exposed with authtoken + /* + SessionContext sc = SessionContext.getContext(); + AuthToken authToken = (AuthToken) sc.get(SessionContext.AUTH_TOKEN); + + AuthzToken authzTok = null; + CMS.debug("UserGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CHECK_AUTHZ_SUB")); + // hardcoded for now .. just testing + try { + authzTok = mAuthz.authorize("DirAclAuthz", authToken, RES_GROUP, "read"); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_AUTH_CALL_FAIL",e.toString())); + } + if (AuthzToken.AUTHZ_STATUS_FAIL.equals(authzTok.get(AuthzToken.TOKEN_AUTHZ_STATUS))) { + // audit would have been needed here if this weren't just a test... + + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_AUTHS")); + + sendResponse(ERROR, + MessageFormatter.getLocalizedString( + getLocale(req), + AdminResources.class.getName(), + AdminResources.SRVLT_FAIL_AUTHS), + null, resp); + return; + } + */ + + try { + ISubsystem subsystem = CMS.getSubsystem("ca"); + if (subsystem != null) + AUTHZ_RES_NAME = RES_CA_GROUP; + subsystem = CMS.getSubsystem("ra"); + if (subsystem != null) + AUTHZ_RES_NAME = RES_RA_GROUP; + subsystem = CMS.getSubsystem("kra"); + if (subsystem != null) + AUTHZ_RES_NAME = RES_KRA_GROUP; + subsystem = CMS.getSubsystem("ocsp"); + if (subsystem != null) + AUTHZ_RES_NAME = RES_OCSP_GROUP; + subsystem = CMS.getSubsystem("tks"); + if (subsystem != null) + AUTHZ_RES_NAME = RES_TKS_GROUP; + if (scope != null) { + if (scope.equals(ScopeDef.SC_USER_TYPE)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + + getUserType(req, resp); + return; + } + + if (op.equals(OpDef.OP_READ)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GROUPS)) { + findGroup(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USERS)) { + findUser(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USER_CERTS)) { + findUserCerts(req, resp, clientLocale); + return; + } + } else if (op.equals(OpDef.OP_MODIFY)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GROUPS)) { + modifyGroup(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USERS)) { + modifyUser(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USER_CERTS)) { + modifyUserCert(req, resp); + return; + } + } else if (op.equals(OpDef.OP_ADD)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GROUPS)) { + addGroup(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USERS)) { + addUser(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USER_CERTS)) { + addUserCert(req, resp); + return; + } + } else if (op.equals(OpDef.OP_DELETE)) { + mOp = "modify"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GROUPS)) { + removeGroup(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USERS)) { + removeUser(req, resp); + return; + } + } else if (op.equals(OpDef.OP_SEARCH)) { + mOp = "read"; + if ((mToken = super.authorize(req)) == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_AUTHZ_FAILED"), + null, resp); + return; + } + if (scope.equals(ScopeDef.SC_GROUPS)) { + findGroups(req, resp); + return; + } else if (scope.equals(ScopeDef.SC_USERS)) { + findUsers(req, resp); + return; + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_INVALID_OP_SCOPE")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_INVALID_OP_SCOPE"), + null, resp); + return; + } + } + } // if + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, e.toString()); + sendResponse(ERROR, e.toString(getLocale(req)), + null, resp); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + log(ILogger.LL_FAILURE, CMS.getLogMessage(" ADMIN_SRVLT_FAIL_PERFORM")); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_FAILED"), + null, resp); + return; + } + } + + private void getUserType(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String id = super.getParameter(req, Constants.RS_ID); + IUser user = mMgr.getUser(id); + String val = user.getUserType(); + + if (val == null || val.equals("")) + val = "noType"; + NameValuePairs params = new NameValuePairs(); + + params.put(Constants.PR_USER_TYPE, val); + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Searches for users in LDAP directory. List uids only + * + * Request/Response Syntax: + * http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + */ + private synchronized void findUsers(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + Enumeration<IUser> e = null; + + try { + e = mMgr.listUsers("*"); + } catch (Exception ex) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp); + return; + } + + StringBuffer sb = new StringBuffer(); + int i = 0; + + while (e.hasMoreElements()) { + IUser user = e.nextElement(); + + if (i > 0) { + sb.append(";"); + sb.append(user.getUserID()); + sb.append(":"); + sb.append(user.getFullName()); + } else { + sb.append(user.getUserID()); + sb.append(":"); + sb.append(user.getFullName()); + } + i++; + } + params.put("userInfo", sb.toString()); + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * List user information. Certificates covered in a separate + * protocol for findUserCerts(). List of group memberships are + * also provided. + * + * Request/Response Syntax: + * http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + */ + private synchronized void findUser(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + //get id first + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + NameValuePairs params = new NameValuePairs(); + + IUser user = null; + + try { + user = mMgr.getUser(id); + } catch (Exception e) { + e.printStackTrace(); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp); + return; + } + + if (user != null) { + params.put(Constants.PR_USER_FULLNAME, user.getFullName()); + params.put(Constants.PR_USER_EMAIL, user.getEmail()); + params.put(Constants.PR_USER_PHONE, user.getPhone()); + params.put(Constants.PR_USER_STATE, user.getState()); + + // get list of groups, and get a list of those that this + // uid belongs to + Enumeration<IGroup> e = null; + + try { + e = mMgr.findGroups("*"); + } catch (Exception ex) { + ex.printStackTrace(); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp); + return; + } + + StringBuffer grpString = new StringBuffer(); + + while (e.hasMoreElements()) { + IGroup group = e.nextElement(); + + if (group.isMember(id) == true) { + if (grpString.length() != 0) { + grpString.append(","); + } + grpString.append(group.getGroupID()); + } + } + + params.put(Constants.PR_USER_GROUP, grpString.toString()); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_NOT_EXIST"), null, resp); + return; + } + + /** + * List user certificate(s) + * + * Request/Response Syntax: + * http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + */ + private synchronized void findUserCerts(HttpServletRequest req, + HttpServletResponse resp, Locale clientLocale) + throws ServletException, + IOException, EBaseException { + + //get id first + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + NameValuePairs params = new NameValuePairs(); + + IUser user = null; + + try { + user = mMgr.getUser(id); + } catch (Exception e) { + e.printStackTrace(); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_NOT_EXIST"), null, resp); + return; + } + + if (user == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_USER_NOT_EXIST")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_NOT_EXIST"), null, resp); + return; + } + + X509Certificate[] certs = + (X509Certificate[]) user.getX509Certificates(); + + if (certs != null) { + for (int i = 0; i < certs.length; i++) { + ICertPrettyPrint print = CMS.getCertPrettyPrint(certs[i]); + + // add base64 encoding + String base64 = CMS.getEncodedCert(certs[i]); + + // pretty print certs + params.put(getCertificateString(certs[i]), + print.toString(clientLocale) + "\n" + base64); + } + sendResponse(SUCCESS, null, params, resp); + return; + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * Converts certificate into string format. + */ + protected String getCertificateString(X509Certificate cert) { + if (cert == null) { + return null; + } + + // note that it did not represent a certificate fully + return cert.getVersion() + ";" + cert.getSerialNumber().toString() + + ";" + cert.getIssuerDN() + ";" + cert.getSubjectDN(); + } + + /** + * Searchess for groups in LDAP server + * + * Request/Response Syntax: + * http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#group + */ + private synchronized void findGroups(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + Enumeration<IGroup> e = null; + + try { + e = mMgr.listGroups("*"); + } catch (Exception ex) { + ex.printStackTrace(); + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp); + return; + } + + while (e.hasMoreElements()) { + IGroup group = e.nextElement(); + String desc = group.getDescription(); + + if (desc != null) { + params.put(group.getGroupID(), desc); + } else { + params.put(group.getGroupID(), ""); + } + } + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * finds a group + * Request/Response Syntax: + * http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + */ + private synchronized void findGroup(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + //get id first + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + Enumeration<IGroup> e = null; + + try { + e = mMgr.findGroups(id); + } catch (Exception ex) { + ex.printStackTrace(); + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp); + return; + } + + if (e.hasMoreElements()) { + IGroup group = e.nextElement(); + + params.put(Constants.PR_GROUP_GROUP, group.getGroupID()); + params.put(Constants.PR_GROUP_DESC, + group.getDescription()); + + Enumeration<String> members = group.getMemberNames(); + StringBuffer membersString = new StringBuffer(); + + if (members != null) { + while (members.hasMoreElements()) { + if (membersString.length() != 0) { + membersString.append(", "); + } + + String mn = members.nextElement(); + + membersString.append(mn); + } + } + + params.put(Constants.PR_GROUP_USER, membersString.toString()); + + sendResponse(SUCCESS, null, params, resp); + return; + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_GROUP_NOT_EXIST")); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_GROUP_NOT_EXIST"), null, resp); + return; + + } + } + + /** + * Adds a new user to LDAP server + * <P> + * + * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void addUser(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + if (id.indexOf(BACK_SLASH) != -1) { + // backslashes (BS) are not allowed + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_RS_ID_BS")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_RS_ID_BS"), + null, resp); + return; + } + + if (id.equals(SYSTEM_USER)) { + // backslashes (BS) are not allowed + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_SPECIAL_ID", id)); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_SPECIAL_ID", id), + null, resp); + return; + } + + IUser user = mMgr.createUser(id); + String fname = super.getParameter(req, Constants.PR_USER_FULLNAME); + + if ((fname == null) || (fname.length() == 0)) { + String msg = CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED_1", "full name"); + + log(ILogger.LL_FAILURE, msg); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, msg, null, resp); + return; + } else + user.setFullName(fname); + + String email = super.getParameter(req, Constants.PR_USER_EMAIL); + + if (email != null) { + user.setEmail(email); + } else { + user.setEmail(""); + } + String pword = super.getParameter(req, Constants.PR_USER_PASSWORD); + + if (pword != null && !pword.equals("")) { + IPasswordCheck passwdCheck = CMS.getPasswordChecker(); + + if (!passwdCheck.isGoodPassword(pword)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EUsrGrpException(passwdCheck.getReason(pword)); + + //UsrGrpResources.BAD_PASSWD); + } + + user.setPassword(pword); + } else { + user.setPassword(""); + } + String phone = super.getParameter(req, Constants.PR_USER_PHONE); + + if (phone != null) { + user.setPhone(phone); + } else { + user.setPhone(""); + } + String userType = super.getParameter(req, Constants.PR_USER_TYPE); + + if (userType != null) { + user.setUserType(userType); + } else { + user.setUserType(""); + } + String userState = super.getParameter(req, Constants.PR_USER_STATE); + + if (userState != null) { + user.setState(userState); + } + + try { + mMgr.addUser(user); + + // if group is specified, add user to group + String groupName = super.getParameter(req, + Constants.PR_USER_GROUP); + + if (groupName != null) { + Enumeration<IGroup> e = null; + + try { + e = mMgr.findGroups(groupName); + } catch (Exception ex) { + ex.printStackTrace(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp); + return; + } + + if (e.hasMoreElements()) { + IGroup group = e.nextElement(); + + group.addMemberName(id); + try { + mMgr.modifyGroup(group); + } catch (Exception ex) { + log(ILogger.LL_FAILURE, ex.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp); + return; + } + } + // for audit log + SessionContext sContext = SessionContext.getContext(); + String adminId = (String) sContext.get(SessionContext.USER_ID); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP, + AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT, + new Object[] { adminId, id, groupName } + ); + } + + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (EUsrGrpException e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + if (user.getUserID() == null) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED_1", "uid"), null, resp); + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp); + } + return; + } catch (LDAPException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ADD_USER_FAIL", e.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_ADD_FAILED"), null, resp); + return; + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Adds a certificate to a user + * <P> + * + * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void addUserCert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + IUser user = mMgr.createUser(id); + String certS = super.getParameter(req, Constants.PR_USER_CERT); + String certsString = Cert.stripBrackets(certS); + + // no cert is a success + if (certsString == null) { + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + // only one cert added per operation + X509Certificate certs[] = null; + + // Base64 decode cert + + try { + byte bCert[] = Utils.base64decode(certsString); + X509Certificate cert = new X509CertImpl(bCert); + + certs = new X509Certificate[1]; + certs[0] = cert; + } catch (CertificateException e) { + // cert chain direction + boolean assending = true; + + // could it be a pkcs7 blob? + CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_IS_PK_BLOB")); + byte p7Cert[] = Utils.base64decode(certsString); + + try { + CryptoManager manager = CryptoManager.getInstance(); + + PKCS7 pkcs7 = new PKCS7(p7Cert); + + X509Certificate p7certs[] = pkcs7.getCertificates(); + + if (p7certs.length == 0) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp); + return; + } + // fix for 370099 - cert ordering can not be assumed + // find out the ordering ... + certs = new X509Certificate[p7Cert.length]; + + // self-signed and alone? take it. otherwise test + // the ordering + if (p7certs[0].getSubjectDN().toString().equals( + p7certs[0].getIssuerDN().toString()) && + (p7certs.length == 1)) { + certs[0] = p7certs[0]; + CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_SINGLE_CERT_IMPORT")); + } else if (p7certs[0].getIssuerDN().toString().equals(p7certs[1].getSubjectDN().toString())) { + certs[0] = p7certs[0]; + CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_CHAIN_ACEND_ORD")); + } else if (p7certs[1].getIssuerDN().toString().equals(p7certs[0].getSubjectDN().toString())) { + assending = false; + CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_CHAIN_DESC_ORD")); + certs[0] = p7certs[p7certs.length - 1]; + } else { + // not a chain, or in random order + CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_CERT_BAD_CHAIN")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp); + return; + } + + CMS.debug("UsrGrpAdminServlet: " + + CMS.getLogMessage("ADMIN_SRVLT_CHAIN_STORED_DB", String.valueOf(p7certs.length))); + + int j = 0; + int jBegin = 0; + int jEnd = 0; + + if (assending == true) { + jBegin = 1; + jEnd = p7certs.length; + } else { + jBegin = 0; + jEnd = p7certs.length - 1; + } + // store the chain into cert db, except for the user cert + for (j = jBegin; j < jEnd; j++) { + CMS.debug("UsrGrpAdminServlet: " + + CMS.getLogMessage("ADMIN_SRVLT_CERT_IN_CHAIN", String.valueOf(j), + String.valueOf(p7certs[j].getSubjectDN()))); + org.mozilla.jss.crypto.X509Certificate leafCert = + null; + + leafCert = + manager.importCACertPackage(p7certs[j].getEncoded()); + + if (leafCert == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_LEAF_CERT_NULL")); + } else { + CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_LEAF_CERT_NON_NULL")); + } + + if (leafCert instanceof InternalCertificate) { + ((InternalCertificate) leafCert).setSSLTrust( + InternalCertificate.VALID_CA | + InternalCertificate.TRUSTED_CA | + InternalCertificate.TRUSTED_CLIENT_CA); + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NOT_INTERNAL_CERT", + String.valueOf(p7certs[j].getSubjectDN()))); + } + } + + /* + } catch (CryptoManager.UserCertConflictException ex) { + // got a "user cert" in the chain, most likely the CA + // cert of this instance, which has a private key. Ignore + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_PKS7_IGNORED", ex.toString())); + */ + } catch (Exception ex) { + //----- + log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_ERROR", ex.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_ERROR"), null, resp); + return; + } + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_O_ERROR", e.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_O_ERROR"), null, resp); + return; + } + + try { + CMS.debug("UsrGrpAdminServlet: " + CMS.getLogMessage("ADMIN_SRVLT_BEFORE_VALIDITY")); + certs[0].checkValidity(); // throw exception if fails + + user.setX509Certificates(certs); + mMgr.addUserCert(user); + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + + } catch (CertificateExpiredException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ADD_CERT_EXPIRED", + String.valueOf(certs[0].getSubjectDN()))); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_EXPIRED"), null, resp); + return; + } catch (CertificateNotYetValidException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("USRGRP_SRVLT_CERT_NOT_YET_VALID", + String.valueOf(certs[0].getSubjectDN()))); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_CERT_NOT_YET_VALID"), null, resp); + return; + + } catch (LDAPException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + if (e.getLDAPResultCode() == LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_USER_CERT_EXISTS"), null, resp); + } else { + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp); + } + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp); + return; + } + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Removes a certificate for a user + * <P> + * + * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + * <P> + * + * In this method, "certDN" is actually a combination of version, serialNumber, issuerDN, and SubjectDN. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void modifyUserCert(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + IUser user = mMgr.createUser(id); + String certDN = super.getParameter(req, Constants.PR_USER_CERT); + + // no certDN is a success + if (certDN == null) { + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } + + user.setCertDN(certDN); + try { + mMgr.removeUserCert(user); + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp); + return; + } + // } catch( EBaseException eAudit1 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * removes a user. user not removed if belongs to any group + * (Administrators should remove the user from "uniquemember" of + * any group he/she belongs to before trying to remove the user + * itself. + * <P> + * + * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void removeUser(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + //get id first + String id = super.getParameter(req, Constants.RS_ID); + boolean mustDelete = false; + int index = 0; + + if ((index = id.lastIndexOf(":true")) != -1) { + id = id.substring(0, index); + mustDelete = true; + } + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + // get list of groups, and see if uid belongs to any + Enumeration<IGroup> e = null; + + try { + e = mMgr.findGroups("*"); + } catch (Exception ex) { + ex.printStackTrace(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, CMS.getUserMessage(getLocale(req), "CMS_INTERNAL_ERROR"), null, resp); + return; + } + + while (e.hasMoreElements()) { + IGroup group = (IGroup) e.nextElement(); + + if (group.isMember(id) == true) { + if (mustDelete) { + mMgr.removeUserFromGroup(group, id); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_FAIL_USER_RMV_G"), + null, resp); + return; + } + } + } + + // comes out clean of group membership...now remove user + try { + mMgr.removeUser(id); + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (Exception ex) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_SRVLT_FAIL_USER_RMV"), null, resp); + return; + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * Adds a new group in local scope. + * <P> + * + * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#group + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void addGroup(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + //get id first + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + IGroup group = mMgr.createGroup(id); + String members = super.getParameter(req, + Constants.PR_GROUP_USER); + String desc = super.getParameter(req, + Constants.PR_GROUP_DESC); + + if (desc != null) { + group.set("description", (Object) desc); + } else { + group.set("description", (Object) ""); + } + + if (members != null) { + StringTokenizer st = new StringTokenizer(members, ","); + + while (st.hasMoreTokens()) { + group.addMemberName(st.nextToken()); + } + } + + // allow adding a group with no members + try { + mMgr.addGroup(group); + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (Exception e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_GROUP_ADD_FAILED"), + null, resp); + return; + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * removes a group + * <P> + * + * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#group + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void removeGroup(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + //get id first + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + // if fails, let the exception fall through + mMgr.removeGroup(id); + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + /** + * modifies a group + * <P> + * + * last person of the super power group "Certificate Server Administrators" can never be removed. + * <P> + * + * http://warp.mcom.com/server/certificate/columbo/design/ ui/admin-protocol-definition.html#group + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void modifyGroup(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + //get id first + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + IGroup group = mMgr.createGroup(id); + + String desc = super.getParameter(req, + Constants.PR_GROUP_DESC); + + if (desc != null) { + group.set("description", (Object) desc); + } + + String members = super.getParameter(req, Constants.PR_GROUP_USER); + + if (members != null) { + StringTokenizer st = new StringTokenizer(members, ","); + + String groupName = group.getName(); + boolean multiRole = true; + + try { + multiRole = mConfig.getBoolean(MULTI_ROLE_ENABLE); + } catch (Exception eee) { + } + while (st.hasMoreTokens()) { + String memberName = st.nextToken(); + if (multiRole) { + group.addMemberName(memberName); + } else { + if (isGroupInMultiRoleEnforceList(groupName)) { + if (!isDuplicate(groupName, memberName)) { + group.addMemberName(memberName); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getUserMessage("CMS_BASE_DUPLICATE_ROLES", memberName)); + } + } else { + group.addMemberName(memberName); + } + } + } + } + + // allow adding a group with no members, except "Certificate + // Server Administrators" + try { + mMgr.modifyGroup(group); + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_GROUP_MODIFY_FAILED"), + null, resp); + return; + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private boolean isGroupInMultiRoleEnforceList(String groupName) { + String groupList = null; + + if (groupName == null || groupName.equals("")) { + return true; + } + if (mMultiRoleGroupEnforceList == null) { + try { + groupList = mConfig.getString(MULTI_ROLE_ENFORCE_GROUP_LIST); + } catch (Exception e) { + } + + if (groupList != null && !groupList.equals("")) { + mMultiRoleGroupEnforceList = groupList.split(","); + for (int j = 0; j < mMultiRoleGroupEnforceList.length; j++) { + mMultiRoleGroupEnforceList[j] = mMultiRoleGroupEnforceList[j].trim(); + } + } + } + + if (mMultiRoleGroupEnforceList == null) + return true; + + for (int i = 0; i < mMultiRoleGroupEnforceList.length; i++) { + if (groupName.equals(mMultiRoleGroupEnforceList[i])) { + return true; + } + } + return false; + } + + private boolean isDuplicate(String groupName, String memberName) { + Enumeration<IGroup> groups = null; + + // Let's not mess with users that are already a member of this group + boolean isMember = false; + try { + isMember = mMgr.isMemberOf(memberName, groupName); + } catch (Exception e) { + } + + if (isMember == true) { + return false; + } + try { + groups = mMgr.listGroups("*"); + while (groups.hasMoreElements()) { + IGroup group = groups.nextElement(); + String name = group.getName(); + Enumeration<IGroup> g = mMgr.findGroups(name); + IGroup g1 = g.nextElement(); + if (!name.equals(groupName)) { + if (isGroupInMultiRoleEnforceList(name)) { + Enumeration<String> members = g1.getMemberNames(); + while (members.hasMoreElements()) { + String m1 = members.nextElement(); + if (m1.equals(memberName)) + return true; + } + } + } + } + } catch (Exception e) { + } + + return false; + } + + /** + * Modifies an existing user in local scope. + * <P> + * + * Request/Response Syntax: http://warp.mcom.com/server/certificate/columbo/design/ + * ui/admin-protocol-definition.html#user-admin + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_ROLE used when configuring role information (anything under + * users/groups) + * </ul> + * + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception ServletException a servlet error has occurred + * @exception IOException an input/output error has occurred + * @exception EBaseException an error has occurred + */ + private synchronized void modifyUser(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + //get id first + String id = super.getParameter(req, Constants.RS_ID); + + if (id == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_NULL_RS_ID")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_NULL_RS_ID"), + null, resp); + return; + } + + IUser user = mMgr.createUser(id); + String fname = super.getParameter(req, Constants.PR_USER_FULLNAME); + + if ((fname == null) || (fname.length() == 0)) { + String msg = + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED", "full name"); + + log(ILogger.LL_FAILURE, msg); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, msg, null, resp); + return; + } else + user.setFullName(fname); + + String email = super.getParameter(req, Constants.PR_USER_EMAIL); + + if (email != null) { + user.setEmail(email); + } + String pword = super.getParameter(req, Constants.PR_USER_PASSWORD); + + if ((pword != null) && (!pword.equals(""))) { + IPasswordCheck passwdCheck = CMS.getPasswordChecker(); + + if (!passwdCheck.isGoodPassword(pword)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EUsrGrpException(passwdCheck.getReason(pword)); + + //UsrGrpResources.BAD_PASSWD); + } + + user.setPassword(pword); + } + String phone = super.getParameter(req, Constants.PR_USER_PHONE); + + if (phone != null) { + user.setPhone(phone); + } + + String userState = super.getParameter(req, Constants.PR_USER_STATE); + if (userState != null) { + user.setState(userState); + } + + try { + mMgr.modifyUser(user); + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_USRGRP_USER_MOD_FAILED"), null, resp); + return; + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } catch (IOException eAudit2) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit2; + // } catch( ServletException eAudit3 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } + + private void log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_USRGRP, + level, "UsrGrpAdminServlet: " + msg); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java b/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java new file mode 100644 index 000000000..acddba559 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/CMSResourceService.java @@ -0,0 +1,69 @@ +// --- 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) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.base; + +import java.security.cert.CertificateEncodingException; + +import javax.ws.rs.core.CacheControl; +import javax.ws.rs.core.EntityTag; +import javax.ws.rs.core.Request; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.cms.servlet.cert.model.CertificateData; + +/** + * Base class for CMS RESTful resources + * + * @author alee + * + */ +public class CMSResourceService { + public static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----"; + public static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----"; + + // caching parameters + protected static final int DEFAULT_LONG_CACHE_LIFETIME = 1000; + + protected Response sendConditionalGetResponse(int ctime, Object object, Request request) { + CacheControl cc = new CacheControl(); + cc.setMaxAge(ctime); + EntityTag tag = new EntityTag(Integer.toString(object.hashCode())); + + ResponseBuilder builder = request.evaluatePreconditions(tag); + if (builder != null) { + builder.cacheControl(cc); + return builder.build(); + } + + builder = Response.ok(object); + builder.cacheControl(cc); + builder.tag(tag); + return builder.build(); + } + + public CertificateData createCertificateData(org.mozilla.jss.crypto.X509Certificate cert) + throws CertificateEncodingException { + CertificateData data = new CertificateData(); + String b64 = HEADER + CMS.BtoA(cert.getEncoded()) + TRAILER; + data.setB64(b64); + return data; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java b/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java new file mode 100644 index 000000000..c0931ee2f --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java @@ -0,0 +1,2294 @@ +// --- 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.base; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Random; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.pkcs.ContentInfo; +import netscape.security.pkcs.PKCS7; +import netscape.security.pkcs.SignerInfo; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.apps.ICommandQueue; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cms.servlet.common.CMSFileLoader; +import com.netscape.cms.servlet.common.CMSGateway; +import com.netscape.cms.servlet.common.CMSLoadTemplate; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.GenErrorTemplateFiller; +import com.netscape.cms.servlet.common.GenPendingTemplateFiller; +import com.netscape.cms.servlet.common.GenRejectedTemplateFiller; +import com.netscape.cms.servlet.common.GenSuccessTemplateFiller; +import com.netscape.cms.servlet.common.GenSvcPendingTemplateFiller; +import com.netscape.cms.servlet.common.GenUnexpectedErrorTemplateFiller; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cms.servlet.common.ServletUtils; +import com.netscape.cmsutil.util.Utils; +import com.netscape.cmsutil.xml.XMLObject; + +/** + * This is the base class of all CS servlet. + * + * @version $Revision$, $Date$ + */ +public abstract class CMSServlet extends HttpServlet { + /** + * + */ + private static final long serialVersionUID = -3886300199374147160L; + // servlet init params + // xxxx todo:Should enforce init param value checking! + public final static String SUCCESS = "0"; + public final static String FAILURE = "1"; + public final static String AUTH_FAILURE = "2"; + + public final static String PROP_ID = "ID"; + public final static String PROP_AUTHORITY = "authority"; + public final static String PROP_AUTHMGR = "AuthMgr"; + public final static String PROP_CLIENTAUTH = "GetClientCert"; + 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 FAILED = "1"; + private final static String HDR_LANG = "accept-language"; + + // final error message - if error and exception templates don't work + // send out this text string directly to output. + + public final static String PROP_FINAL_ERROR_MSG = "finalErrorMsg"; + public final static String ERROR_MSG_TOKEN = "$ERROR_MSG"; + public final static String FINAL_ERROR_MSG = + "<HTML>\n" + + "<BODY BGCOLOR=white>\n" + + "<P>\n" + + "The Certificate System has encountered " + + "an unrecoverable error.\n" + + "<P>\n" + + "Error Message:<BR>\n" + + "<I>$ERROR_MSG</I>\n" + + "<P>\n" + + "Please contact your local administrator for assistance.\n" + + "</BODY>\n" + + "</HTML>\n"; + + // properties from configuration. + + protected final static String PROP_UNAUTHORIZED_TEMPLATE = "unauthorizedTemplate"; + protected final static String UNAUTHORIZED_TEMPLATE = "/GenUnauthorized.template"; + protected final static String PROP_SUCCESS_TEMPLATE = "successTemplate"; + protected final static String SUCCESS_TEMPLATE = "/GenSuccess.template"; + protected final static String PROP_PENDING_TEMPLATE = "pendingTemplate"; + protected final static String PENDING_TEMPLATE = "/GenPending.template"; + protected final static String PROP_SVC_PENDING_TEMPLATE = "svcpendingTemplate"; + protected final static String SVC_PENDING_TEMPLATE = "/GenSvcPending.template"; + protected final static String PROP_REJECTED_TEMPLATE = "rejectedTemplate"; + protected final static String REJECTED_TEMPLATE = "/GenRejected.template"; + protected final static String PROP_ERROR_TEMPLATE = "errorTemplate"; + protected final static String ERROR_TEMPLATE = "/GenError.template"; + protected final static String PROP_EXCEPTION_TEMPLATE = "unexpectedErrorTemplate"; + protected final static String EXCEPTION_TEMPLATE = "/GenUnexpectedError.template"; + + private final static String PROP_UNAUTHOR_TEMPLATE_FILLER = "unauthorizedTemplateFiller"; + protected final static String PROP_SUCCESS_TEMPLATE_FILLER = "successTemplateFiller"; + private final static String PROP_ERROR_TEMPLATE_FILLER = "errorTemplateFiller"; + private final static String PROP_PENDING_TEMPLATE_FILLER = "pendingTemplateFiller"; + private final static String PROP_SVC_PENDING_TEMPLATE_FILLER = "svcpendingTemplateFiller"; + private final static String PROP_REJECTED_TEMPLATE_FILLER = "rejectedTemplateFiller"; + private final static String PROP_EXCEPTION_TEMPLATE_FILLER = "exceptionTemplateFiller"; + + protected final static String RA_AGENT_GROUP = "Registration Manager Agents"; + protected final static String CA_AGENT_GROUP = "Certificate Manager Agents"; + protected final static String KRA_AGENT_GROUP = "Data Recovery Manager Agents"; + protected final static String OCSP_AGENT_GROUP = "Online Certificate Status Manager Agents"; + protected final static String TRUSTED_RA_GROUP = "Trusted Managers"; + protected final static String ADMIN_GROUP = "Administrators"; + + // default http params NOT to save in request.(config values added to list ) + private static final String PROP_DONT_SAVE_HTTP_PARAMS = "dontSaveHttpParams"; + private static final String[] DONT_SAVE_HTTP_PARAMS = { "pwd", "password", "passwd", + "challengePassword", "confirmChallengePassword" }; + + // default http headers to save in request. (config values added to list) + private static final String PROP_SAVE_HTTP_HEADERS = "saveHttpHeaders"; + private static final String[] SAVE_HTTP_HEADERS = { "accept-language", "user-agent", }; + + // request prefixes to distinguish from other request attributes. + public static final String PFX_HTTP_HEADER = "HTTP_HEADER"; + public static final String PFX_HTTP_PARAM = "HTTP_PARAM"; + public static final String PFX_AUTH_TOKEN = "AUTH_TOKEN"; + + /* input http params */ + protected final static String AUTHMGR_PARAM = "authenticator"; + + /* fixed credential passed to auth managers */ + protected final static String CERT_AUTH_CRED = "sslClientCert"; + + public static final String CERT_ATTR = + "javax.servlet.request.X509Certificate"; + + // members. + + protected boolean mRenderResult = true; + protected String mFinalErrorMsg = FINAL_ERROR_MSG; + protected Hashtable<Integer, CMSLoadTemplate> mTemplates = new Hashtable<Integer, CMSLoadTemplate>(); + + protected ServletConfig mServletConfig = null; + protected ServletContext mServletContext = null; + private CMSFileLoader mFileLoader = null; + + protected Vector<String> mDontSaveHttpParams = new Vector<String>(); + protected Vector<String> mSaveHttpHeaders = new Vector<String>(); + + protected String mId = null; + protected IConfigStore mConfig = null; + + // the authority, RA, CA, KRA this servlet is serving. + protected IAuthority mAuthority = null; + protected IRequestQueue mRequestQueue = null; + + // system logger. + protected ILogger mLogger = CMS.getLogger(); + protected int mLogCategory = ILogger.S_OTHER; + private MessageDigest mSHADigest = null; + + protected String mGetClientCert = "false"; + protected String mAuthMgr = null; + protected IAuthzSubsystem mAuthz = null; + + protected String mAclMethod = null; + protected String mAuthzResourceName = null; + + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + protected String mOutputTemplatePath = null; + private IUGSubsystem mUG = (IUGSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_UG); + + private final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL = + "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4"; + private final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3"; + private final static String LOGGING_SIGNED_AUDIT_AUTHZ_FAIL = + "LOGGING_SIGNED_AUDIT_AUTHZ_FAIL_4"; + private final static String LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS_4"; + private final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME = + "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3"; + + public CMSServlet() { + } + + public static Hashtable<String, String> toHashtable(HttpServletRequest req) { + Hashtable<String, String> httpReqHash = new Hashtable<String, String>(); + Enumeration<?> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + + httpReqHash.put(name, req.getParameter(name)); + } + return httpReqHash; + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + mId = sc.getInitParameter(PROP_ID); + + try { + mAclMethod = ServletUtils.initializeAuthz(sc, mAuthz, mId); + } catch (ServletException e) { + log(ILogger.LL_FAILURE, e.toString()); + throw e; + } + + mConfig = CMS.getConfigStore().getSubStore(CMSGateway.PROP_CMSGATEWAY); + mServletConfig = sc; + mServletContext = sc.getServletContext(); + mFileLoader = new CMSFileLoader(); + + mGetClientCert = sc.getInitParameter(PROP_CLIENTAUTH); + mAuthMgr = sc.getInitParameter(PROP_AUTHMGR); + mAuthzResourceName = sc.getInitParameter(PROP_RESOURCEID); + mOutputTemplatePath = sc.getInitParameter("templatePath"); + + String authority = sc.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) + CMS.getSubsystem(authority); + if (mAuthority != null) + mRequestQueue = mAuthority.getRequestQueue(); + + // set default templates. + setDefaultTemplates(sc); + + // for logging to the right authority category. + if (mAuthority == null) { + mLogCategory = ILogger.S_OTHER; + } else { + if (mAuthority instanceof ICertificateAuthority) + mLogCategory = ILogger.S_CA; + else if (mAuthority instanceof IRegistrationAuthority) + mLogCategory = ILogger.S_RA; + else if (mAuthority instanceof IKeyRecoveryAuthority) + mLogCategory = ILogger.S_KRA; + else + mLogCategory = ILogger.S_OTHER; + } + + try { + // get final error message. + // used when templates can't even be loaded. + String eMsg = + sc.getInitParameter(PROP_FINAL_ERROR_MSG); + + if (eMsg != null) + mFinalErrorMsg = eMsg; + + // get any configured templates. + Enumeration<CMSLoadTemplate> templs = mTemplates.elements(); + + while (templs.hasMoreElements()) { + CMSLoadTemplate templ = (CMSLoadTemplate) templs.nextElement(); + + if (templ == null || templ.mPropName == null) { + continue; + } + String tName = + sc.getInitParameter(templ.mPropName); + + if (tName != null) + templ.mTemplateName = tName; + String fillerName = + sc.getInitParameter(templ.mFillerPropName); + + if (fillerName != null) { + ICMSTemplateFiller filler = newFillerObject(fillerName); + + if (filler != null) + templ.mFiller = filler; + } + } + + // get http params NOT to store in a IRequest and + // get http headers TO store in a IRequest. + getDontSaveHttpParams(sc); + getSaveHttpHeaders(sc); + } catch (Exception e) { + // should never occur since we provide defaults above. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_CONF_TEMP_PARAMS", + e.toString())); + throw new ServletException(e.toString()); + } + + try { + mSHADigest = MessageDigest.getInstance("SHA1"); + } catch (NoSuchAlgorithmException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_CONF_TEMP_PARAMS", + e.toString())); + throw new ServletException(e.toString()); + } + } + + public String getId() { + return mId; + } + + public String getAuthMgr() { + return mAuthMgr; + } + + public boolean isClientCertRequired() { + if (mGetClientCert != null && mGetClientCert.equals("true")) + return true; + else + return false; + } + + public void outputHttpParameters(HttpServletRequest httpReq) { + CMS.debug("CMSServlet:service() uri = " + httpReq.getRequestURI()); + Enumeration<?> paramNames = httpReq.getParameterNames(); + while (paramNames.hasMoreElements()) { + String pn = (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 (pn.startsWith("__") || + pn.endsWith("password") || + pn.endsWith("passwd") || + pn.endsWith("pwd") || + pn.equalsIgnoreCase("admin_password_again") || + pn.equalsIgnoreCase("directoryManagerPwd") || + pn.equalsIgnoreCase("bindpassword") || + pn.equalsIgnoreCase("bindpwd") || + pn.equalsIgnoreCase("passwd") || + pn.equalsIgnoreCase("password") || + pn.equalsIgnoreCase("pin") || + pn.equalsIgnoreCase("pwd") || + pn.equalsIgnoreCase("pwdagain") || + pn.startsWith("p12Password") || + pn.equalsIgnoreCase("uPasswd")) { + CMS.debug("CMSServlet::service() param name='" + pn + + "' value='(sensitive)'"); + } else { + CMS.debug("CMSServlet::service() param name='" + pn + + "' value='" + httpReq.getParameter(pn) + "'"); + } + } + } + + public void service(HttpServletRequest httpReq, + HttpServletResponse httpResp) + throws ServletException, IOException { + + boolean running_state = CMS.isInRunningState(); + + if (!running_state) + throw new IOException( + "CS server is not ready to serve."); + + try { + if (CMS.getConfigStore().getBoolean("useThreadNaming", false)) { + String currentName = Thread.currentThread().getName(); + + Thread.currentThread().setName(currentName + "-" + httpReq.getServletPath()); + } + } catch (Exception e) { + } + + httpReq.setCharacterEncoding("UTF-8"); + + if (CMS.debugOn()) { + outputHttpParameters(httpReq); + } + CMS.debug("CMSServlet: " + mId + " start to service."); + + // get a cms request + CMSRequest cmsRequest = newCMSRequest(); + + // set argblock + cmsRequest.setHttpParams(CMS.createArgBlock("http-request-params", toHashtable(httpReq))); + + // set http request + cmsRequest.setHttpReq(httpReq); + + // set http response + cmsRequest.setHttpResp(httpResp); + + // set servlet config. + cmsRequest.setServletConfig(mServletConfig); + + // set servlet context. + cmsRequest.setServletContext(mServletContext); + + IArgBlock httpArgs = cmsRequest.getHttpParams(); + + // authenticator value from http overrides the value in web.xml. + String authMgr_http = httpArgs.getValueAsString(AUTHMGR_PARAM, null); + + if (authMgr_http != null) { + mAuthMgr = authMgr_http; + } else { + mAuthMgr = mServletConfig.getInitParameter(PROP_AUTHMGR); + } + + // process request. + ICommandQueue iCommandQueue = CMS.getCommandQueue(); + + try { + if (iCommandQueue.registerProcess(cmsRequest, this) == false) { + cmsRequest.setStatus(CMSRequest.ERROR); + renderResult(cmsRequest); + SessionContext.releaseContext(); + return; + } + long startTime = CMS.getCurrentDate().getTime(); + process(cmsRequest); + renderResult(cmsRequest); + Date endDate = CMS.getCurrentDate(); + long endTime = endDate.getTime(); + if (CMS.debugOn()) { + CMS.debug(CMS.DEBUG_INFORM, "CMSServlet: curDate=" + + endDate + " id=" + mId + " time=" + (endTime - startTime)); + } + iCommandQueue.unRegisterProccess((Object) cmsRequest, (Object) this); + } catch (EBaseException e) { + iCommandQueue.unRegisterProccess((Object) cmsRequest, (Object) this); + // ByteArrayOutputStream os = new ByteArrayOutputStream(); for debugging only + // PrintStream ps = new PrintStream(os); + //e.printStackTrace(ps); + log(e.toString()); + renderException(cmsRequest, e); + } catch (Exception ex) { + iCommandQueue.unRegisterProccess((Object) cmsRequest, (Object) this); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + PrintStream ps = new PrintStream(os); + + ex.printStackTrace(ps); + log(os.toString()); + renderFinalError(cmsRequest, ex); + } + + // destroy SessionContext + SessionContext.releaseContext(); + + return; + } + + /** + * Create a new CMSRequest object. This should be overriden by servlets + * implementing different types of request + * + * @return a new CMSRequest object + */ + protected CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * process an HTTP request. Servlets must override this with their + * own implementation + * + * @throws EBaseException if the servlet was unable to satisfactorily + * process the request + */ + protected void process(CMSRequest cmsRequest) + throws EBaseException { + } + + /** + * Output a template. + * If an error occurs while outputing the template the exception template + * is used to display the error. + * + * @param cmsReq the CS request + */ + protected void renderResult(CMSRequest cmsReq) + throws IOException { + + if (!mRenderResult) + return; + Integer status = cmsReq.getStatus(); + + CMSLoadTemplate ltempl = (CMSLoadTemplate) mTemplates.get(status); + + if (ltempl == null || ltempl.mTemplateName == null) { + // result is previously outputed. + return; + } + ICMSTemplateFiller filler = ltempl.mFiller; + + renderTemplate(cmsReq, ltempl.mTemplateName, filler); + } + + private static final String PRESERVED = "preserved"; + public static final String TEMPLATE_NAME = "templateName"; + + protected void outputArgBlockAsXML(XMLObject xmlObj, Node parent, + String argBlockName, IArgBlock argBlock) { + Node argBlockContainer = xmlObj.createContainer(parent, argBlockName); + + if (argBlock != null) { + Enumeration<String> names = argBlock.getElements(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + String val = argBlock.get(name).toString(); + val = val.trim(); + xmlObj.addItemToContainer(argBlockContainer, name, val); + } + } + } + + protected void outputXML(HttpServletResponse httpResp, CMSTemplateParams params) { + XMLObject xmlObj = null; + try { + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("xml"); + outputArgBlockAsXML(xmlObj, root, "header", params.getHeader()); + outputArgBlockAsXML(xmlObj, root, "fixed", params.getFixed()); + + Enumeration<IArgBlock> records = params.queryRecords(); + Node recordsNode = xmlObj.createContainer(root, "records"); + if (records != null) { + while (records.hasMoreElements()) { + IArgBlock record = (IArgBlock) records.nextElement(); + outputArgBlockAsXML(xmlObj, recordsNode, "record", record); + } + } + + byte[] cb = xmlObj.toByteArray(); + OutputStream os = httpResp.getOutputStream(); + httpResp.setContentType("application/xml"); + httpResp.setContentLength(cb.length); + os.write(cb); + os.flush(); + } catch (Exception e) { + CMS.debug("failed in outputing XML " + e); + } + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException { + try { + IArgBlock httpParams = cmsReq.getHttpParams(); + + Locale[] locale = new Locale[1]; + CMSTemplate template = + getTemplate(templateName, cmsReq.getHttpReq(), locale); + CMSTemplateParams templateParams = null; + + if (filler != null) { + templateParams = filler.getTemplateParams( + cmsReq, mAuthority, locale[0], null); + } + + // just output arg blocks as XML + CMS.debug("CMSServlet.java: renderTemplate"); + String xmlOutput = cmsReq.getHttpReq().getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + CMS.debug("CMSServlet.java: xml parameter detected, returning xml"); + outputXML(cmsReq.getHttpResp(), templateParams); + return; + } + + if (httpParams != null) { + String httpTemplateName = + httpParams.getValueAsString( + TEMPLATE_NAME, null); + + if (httpTemplateName != null) { + templateName = httpTemplateName; + } + } + + if (templateParams == null) + templateParams = new CMSTemplateParams(null, null); + + // #359630 + // inject preserved http parameter into the template + if (httpParams != null) { + String preserved = httpParams.getValueAsString( + PRESERVED, null); + + if (preserved != null) { + IArgBlock fixed = templateParams.getFixed(); + + if (fixed != null) { + fixed.set(PRESERVED, preserved); + } + } + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + template.renderOutput(bos, templateParams); + cmsReq.getHttpResp().setContentType("text/html"); + cmsReq.getHttpResp().setContentLength(bos.size()); + bos.writeTo(cmsReq.getHttpResp().getOutputStream()); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_TEMPLATE", templateName, e.toString())); + renderException(cmsReq, + new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"))); + return; + } + } + + /** + * Output exception (unexpected error) template + * This is different from other templates in that if an exception occurs + * while rendering the exception a message is printed out directly. + * If the message gets an error an IOException is thrown. + * In others if an exception occurs while rendering the template the + * exception template (this) is called. + * <p> + * + * @param cmsReq the CS request to pass to template filler if any. + * @param e the unexpected exception + */ + protected void renderException(CMSRequest cmsReq, EBaseException e) + throws IOException { + try { + Locale[] locale = new Locale[1]; + CMSLoadTemplate loadTempl = + (CMSLoadTemplate) mTemplates.get(CMSRequest.EXCEPTION); + CMSTemplate template = getTemplate(loadTempl.mTemplateName, + cmsReq.getHttpReq(), locale); + ICMSTemplateFiller filler = loadTempl.mFiller; + CMSTemplateParams templateParams = null; + + // When an exception occurs the exit is non-local which probably + // will leave the requestStatus value set to something other + // than CMSRequest.EXCEPTION, so force the requestStatus to + // EXCEPTION since it must be that if we're here. + cmsReq.setStatus(CMSRequest.EXCEPTION); + + if (filler != null) { + templateParams = filler.getTemplateParams( + cmsReq, mAuthority, locale[0], e); + } + if (templateParams == null) { + templateParams = new CMSTemplateParams(null, CMS.createArgBlock()); + } + if (e != null) { + templateParams.getFixed().set( + ICMSTemplateFiller.EXCEPTION, e.toString(locale[0])); + } + + // just output arg blocks as XML + CMS.debug("CMSServlet.java: renderTemplate"); + String xmlOutput = cmsReq.getHttpReq().getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + CMS.debug("CMSServlet.java: xml parameter detected, returning xml"); + outputXML(cmsReq.getHttpResp(), templateParams); + return; + } + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + template.renderOutput(bos, templateParams); + cmsReq.getHttpResp().setContentType("text/html"); + cmsReq.getHttpResp().setContentLength(bos.size()); + bos.writeTo(cmsReq.getHttpResp().getOutputStream()); + } catch (Exception ex) { + renderFinalError(cmsReq, ex); + } + } + + public void renderFinalError(CMSRequest cmsReq, Exception ex) + throws IOException { + // this template is the last resort for all other unexpected + // errors in other templates so we can only output text. + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + httpResp.setContentType("text/html"); + ServletOutputStream out = httpResp.getOutputStream(); + + // replace $ERRORMSG with exception message if included. + String finalErrMsg = mFinalErrorMsg; + int tokenIdx = mFinalErrorMsg.indexOf(ERROR_MSG_TOKEN); + + if (tokenIdx != -1) { + finalErrMsg = + mFinalErrorMsg.substring(0, tokenIdx) + + ex.toString() + + mFinalErrorMsg.substring( + tokenIdx + ERROR_MSG_TOKEN.length()); + } + out.println(finalErrMsg); + return; + } + + /** + * Invalidates a SSL Session. So client auth will happen again. + */ + protected static void invalidateSSLSession(HttpServletRequest httpReq) { + + /* + try { + s = (SSLSocket) ((HTTPRequest) httpReq).getConnection().getSocket(); + } catch (ClassCastException e) { + CMS.getLogger().log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_SSL_NO_INVALIDATE")); + // ignore. + return; + } + try { + s.invalidateSession(); + s.resetHandshake(); + }catch (SocketException se) { + } + */ + return; + } + + /** + * construct a authentication credentials to pass into authentication + * manager. + */ + public static AuthCredentials getAuthCreds( + IAuthManager authMgr, IArgBlock argBlock, X509Certificate clientCert) + throws EBaseException { + // get credentials from http parameters. + String[] reqCreds = authMgr.getRequiredCreds(); + AuthCredentials creds = new AuthCredentials(); + + for (int i = 0; i < reqCreds.length; i++) { + String reqCred = reqCreds[i]; + + if (reqCred.equals(IAuthManager.CRED_SSL_CLIENT_CERT)) { + // cert could be null; + creds.set(reqCred, new X509Certificate[] { clientCert } + ); + } else { + String value = argBlock.getValueAsString(reqCred); + + creds.set(reqCred, value); // value could be null; + } + } + // Inserted by bskim + creds.setArgBlock(argBlock); + // Insert end + return creds; + } + + /** + * get ssl client authenticated certificate + */ + protected X509Certificate + getSSLClientCertificate(HttpServletRequest httpReq) + throws EBaseException { + + X509Certificate cert = null; + + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_INFO, + CMS.getLogMessage("CMSGW_GETTING_SSL_CLIENT_CERT")); + + // iws60 support Java Servlet Spec V2.2, attribute + // javax.servlet.request.X509Certificate now contains array + // of X509Certificates instead of one X509Certificate object + X509Certificate[] allCerts = (X509Certificate[]) httpReq.getAttribute(CERT_ATTR); + + if (allCerts == null || allCerts.length == 0) { + throw new EBaseException("You did not provide a valid certificate for this operation"); + } + + cert = allCerts[0]; + + if (cert == null) { + // just don't have a cert. + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL")); + return null; + } + + // convert to sun's x509 cert interface. + try { + byte[] certEncoded = cert.getEncoded(); + + cert = new X509CertImpl(certEncoded); + } catch (CertificateEncodingException e) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_ENCODE", e.getMessage())); + return null; + } catch (CertificateException e) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_SSL_CL_CERT_FAIL_DECODE", e.getMessage())); + return null; + } + return cert; + } + + /** + * get a template based on result status. + */ + protected CMSTemplate getTemplate( + String templateName, HttpServletRequest httpReq, Locale[] locale) + throws EBaseException, IOException { + // this converts to system dependent file seperator char. + if (mServletConfig == null) { + CMS.debug("CMSServlet:getTemplate() - mServletConfig is null!"); + return null; + } + if (mServletConfig.getServletContext() == null) { + } + if (templateName == null) { + } + String realpath = + mServletConfig.getServletContext().getRealPath("/" + templateName); + + if (realpath == null) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_FIND_TEMPLATE", templateName)); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + File realpathFile = new File(realpath); + File templateFile = + getLangFile(httpReq, realpathFile, locale); + String charSet = httpReq.getCharacterEncoding(); + + if (charSet == null) { + charSet = "UTF8"; + } + CMSTemplate template = + (CMSTemplate) mFileLoader.getCMSFile(templateFile, charSet); + + return template; + } + + /** + * 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); + } + + /** + * get http parameters not to save from configuration. + */ + protected void getDontSaveHttpParams(ServletConfig sc) { + String dontSaveParams = null; + + try { + for (int i = 0; i < DONT_SAVE_HTTP_PARAMS.length; i++) { + mDontSaveHttpParams.addElement(DONT_SAVE_HTTP_PARAMS[i]); + } + dontSaveParams = sc.getInitParameter( + PROP_DONT_SAVE_HTTP_PARAMS); + if (dontSaveParams != null) { + StringTokenizer params = + new StringTokenizer(dontSaveParams, ","); + + while (params.hasMoreTokens()) { + String param = params.nextToken(); + + mDontSaveHttpParams.addElement(param); + } + } + } catch (Exception e) { + // should never happen + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_NO_CONFIG_VALUE", PROP_DONT_SAVE_HTTP_PARAMS, e.toString())); + // default just in case. + for (int i = 0; i < DONT_SAVE_HTTP_PARAMS.length; i++) { + mDontSaveHttpParams.addElement(DONT_SAVE_HTTP_PARAMS[i]); + } + return; + } + } + + /** + * get http headers to save from configuration. + */ + protected void getSaveHttpHeaders(ServletConfig sc) { + try { + // init save http headers. default will always be saved. + for (int i = 0; i < SAVE_HTTP_HEADERS.length; i++) { + mSaveHttpHeaders.addElement(SAVE_HTTP_HEADERS[i]); + } + + // now get from config file if there's more. + String saveHeaders = + sc.getInitParameter(PROP_SAVE_HTTP_HEADERS); + + if (saveHeaders != null) { + StringTokenizer headers = + new StringTokenizer(saveHeaders, ","); + + while (headers.hasMoreTokens()) { + String hdr = headers.nextToken(); + + mSaveHttpHeaders.addElement(hdr); + } + } + } catch (Exception e) { + // should never happen + log(ILogger.LL_WARN, CMS.getLogMessage("CMSGW_NO_CONFIG_VALUE", PROP_SAVE_HTTP_HEADERS, e.toString())); + return; + } + } + + /** + * save http headers in a IRequest. + */ + protected void saveHttpHeaders( + HttpServletRequest httpReq, IRequest req) + throws EBaseException { + Hashtable<String, String> headers = new Hashtable<String, String>(); + Enumeration<String> hdrs = mSaveHttpHeaders.elements(); + + while (hdrs.hasMoreElements()) { + String hdr = hdrs.nextElement(); + String val = httpReq.getHeader(hdr); + + if (val != null) { + headers.put(hdr, val); + } + } + req.setExtData(IRequest.HTTP_HEADERS, headers); + } + + /** + * save http headers in a IRequest. + */ + protected void saveHttpParams( + IArgBlock httpParams, IRequest req) { + Hashtable<String, String> saveParams = new Hashtable<String, String>(); + + Enumeration<String> names = httpParams.elements(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + Enumeration<String> params = mDontSaveHttpParams.elements(); + boolean dosave = true; + + while (params.hasMoreElements()) { + String param = params.nextElement(); + + if (name.equalsIgnoreCase(param)) { + dosave = false; + break; + } + } + if (dosave) { + // kmccarth + // fear not - service() calls toHashtable() which only + // retrieves string values. + // TODO - when we can use JDK5 features we should typecast + // the params until they get here + saveParams.put(name, (String) httpParams.get(name)); + } + } + req.setExtData(IRequest.HTTP_PARAMS, saveParams); + } + + /** + * handy routine for getting a cert record given a serial number. + */ + protected ICertRecord getCertRecord(BigInteger serialNo) { + if (mAuthority == null || + !(mAuthority instanceof ICertificateAuthority)) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_NON_CERT_AUTH")); + return null; + } + ICertificateRepository certdb = + ((ICertificateAuthority) mAuthority).getCertificateRepository(); + + if (certdb == null) { + log(ILogger.LL_WARN, CMS.getLogMessage("CMSGW_CERT_DB_NULL", mAuthority.toString())); + return null; + } + ICertRecord certRecord = null; + + try { + certRecord = certdb.readCertificateRecord(serialNo); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_CERT_REC", serialNo.toString(16), e.toString())); + return null; + } + return certRecord; + } + + /** + * handy routine for validating if a cert is from this CA. + * mAuthority must be a CA. + */ + protected boolean isCertFromCA(X509Certificate cert) { + BigInteger serialno = cert.getSerialNumber(); + X509CertImpl certInDB = (X509CertImpl) getX509Certificate(serialno); + + if (certInDB == null || !certInDB.equals(cert)) + return false; + return true; + } + + /** + * handy routine for checking if a list of certs is from this CA. + * mAuthortiy must be a CA. + */ + protected boolean areCertsFromCA(X509Certificate[] certs) { + for (int i = certs.length - 1; i >= 0; i--) { + if (!isCertFromCA(certs[i])) + return false; + } + return true; + } + + /** + * handy routine for getting a certificate from the certificate + * repository. mAuthority must be a CA. + */ + protected X509Certificate getX509Certificate(BigInteger serialNo) { + if (mAuthority == null || + !(mAuthority instanceof ICertificateAuthority)) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NOT_CERT_AUTH")); + return null; + } + ICertificateRepository certdb = + ((ICertificateAuthority) mAuthority).getCertificateRepository(); + + if (certdb == null) { + log(ILogger.LL_WARN, CMS.getLogMessage("CMSGW_CERT_DB_NULL", mAuthority.toString())); + return null; + } + X509Certificate cert = null; + + try { + cert = certdb.getX509Certificate(serialNo); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_CERT_REC", serialNo.toString(16), e.toString())); + return null; + } + return cert; + } + + /** + * instantiate a new filler from a class name, + * + * @return null if can't be instantiated, new instance otherwise. + */ + protected ICMSTemplateFiller newFillerObject(String fillerClass) { + ICMSTemplateFiller filler = null; + + try { + filler = (ICMSTemplateFiller) + Class.forName(fillerClass).newInstance(); + } catch (Exception e) { + if ((e instanceof RuntimeException)) { + throw (RuntimeException) e; + } else { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_CANT_LOAD_FILLER", fillerClass, e.toString())); + return null; + } + } + return filler; + } + + /** + * set default templates. + * subclasses can override, and should override at least the success + * template + */ + protected void setDefaultTemplates(ServletConfig sc) { + // Subclasses should override these for diff templates and params in + // their constructors. + // Set a template name to null to not use these standard ones. + // When template name is set to null nothing will be displayed. + // Servlet is assumed to have rendered its own output. + // The only exception is the unexpected error template where the + // default one will always be used if template name is null. + String successTemplate = null; + String errorTemplate = null; + String unauthorizedTemplate = null; + String pendingTemplate = null; + String svcpendingTemplate = null; + String rejectedTemplate = null; + String unexpectedErrorTemplate = null; + + String gateway = sc.getInitParameter("interface"); + String authority = sc.getInitParameter(PROP_AUTHORITY); + if (authority == null) { + authority = sc.getInitParameter("authorityId"); + } + + try { + successTemplate = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE); + if (successTemplate == null) { + successTemplate = SUCCESS_TEMPLATE; + if (gateway != null) + //successTemplate = "/"+gateway+successTemplate; + successTemplate = "/" + gateway + successTemplate; + } + + errorTemplate = sc.getInitParameter( + PROP_ERROR_TEMPLATE); + if (errorTemplate == null) { + errorTemplate = ERROR_TEMPLATE; + if (gateway != null) + //errorTemplate = "/"+gateway+errorTemplate; + errorTemplate = "/" + gateway + errorTemplate; + } + + unauthorizedTemplate = sc.getInitParameter( + PROP_UNAUTHORIZED_TEMPLATE); + if (unauthorizedTemplate == null) { + unauthorizedTemplate = UNAUTHORIZED_TEMPLATE; + if (gateway != null) + //unauthorizedTemplate = "/"+gateway+unauthorizedTemplate; + unauthorizedTemplate = "/" + gateway + unauthorizedTemplate; + } + + pendingTemplate = sc.getInitParameter( + PROP_PENDING_TEMPLATE); + if (pendingTemplate == null) { + pendingTemplate = PENDING_TEMPLATE; + if (gateway != null) + //pendingTemplate = "/"+gateway+pendingTemplate; + pendingTemplate = "/" + gateway + pendingTemplate; + } + + svcpendingTemplate = sc.getInitParameter( + PROP_SVC_PENDING_TEMPLATE); + if (svcpendingTemplate == null) { + svcpendingTemplate = SVC_PENDING_TEMPLATE; + if (gateway != null) + //svcpendingTemplate = "/"+gateway+svcpendingTemplate; + svcpendingTemplate = "/" + gateway + svcpendingTemplate; + } + + rejectedTemplate = sc.getInitParameter( + PROP_REJECTED_TEMPLATE); + if (rejectedTemplate == null) { + rejectedTemplate = REJECTED_TEMPLATE; + if (gateway != null) + //rejectedTemplate = "/"+gateway+rejectedTemplate; + rejectedTemplate = "/" + gateway + rejectedTemplate; + } + + unexpectedErrorTemplate = sc.getInitParameter( + PROP_EXCEPTION_TEMPLATE); + if (unexpectedErrorTemplate == null) { + unexpectedErrorTemplate = EXCEPTION_TEMPLATE; + if (gateway != null) + //unexpectedErrorTemplate = "/"+gateway+unexpectedErrorTemplate; + unexpectedErrorTemplate = "/" + gateway + unexpectedErrorTemplate; + } + } catch (Exception e) { + // this should never happen. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(), + mId)); + } + + mTemplates.put( + CMSRequest.UNAUTHORIZED, + new CMSLoadTemplate( + PROP_UNAUTHORIZED_TEMPLATE, PROP_UNAUTHOR_TEMPLATE_FILLER, + unauthorizedTemplate, null)); + mTemplates.put( + CMSRequest.SUCCESS, + new CMSLoadTemplate( + PROP_SUCCESS_TEMPLATE, PROP_SUCCESS_TEMPLATE_FILLER, + successTemplate, new GenSuccessTemplateFiller())); + mTemplates.put( + CMSRequest.PENDING, + new CMSLoadTemplate( + PROP_PENDING_TEMPLATE, PROP_PENDING_TEMPLATE_FILLER, + pendingTemplate, new GenPendingTemplateFiller())); + mTemplates.put( + CMSRequest.SVC_PENDING, + new CMSLoadTemplate( + PROP_SVC_PENDING_TEMPLATE, PROP_SVC_PENDING_TEMPLATE_FILLER, + svcpendingTemplate, new GenSvcPendingTemplateFiller())); + mTemplates.put( + CMSRequest.REJECTED, + new CMSLoadTemplate( + PROP_REJECTED_TEMPLATE, PROP_REJECTED_TEMPLATE_FILLER, + rejectedTemplate, new GenRejectedTemplateFiller())); + mTemplates.put( + CMSRequest.ERROR, + new CMSLoadTemplate( + PROP_ERROR_TEMPLATE, PROP_ERROR_TEMPLATE_FILLER, + errorTemplate, new GenErrorTemplateFiller())); + mTemplates.put( + CMSRequest.EXCEPTION, + new CMSLoadTemplate( + PROP_EXCEPTION_TEMPLATE, PROP_EXCEPTION_TEMPLATE_FILLER, + unexpectedErrorTemplate, new GenUnexpectedErrorTemplateFiller())); + } + + /** + * handy routine to check if client is navigator based on user-agent. + */ + public static boolean clientIsNav(HttpServletRequest httpReq) { + String useragent = httpReq.getHeader("user-agent"); + + if (useragent.startsWith("Mozilla") && + useragent.indexOf("MSIE") == -1) + return true; + return false; + } + + /** + * handy routine to check if client is msie based on user-agent. + */ + public static boolean clientIsMSIE(HttpServletRequest httpReq) { + String useragent = httpReq.getHeader("user-agent"); + + if (useragent != null && useragent.indexOf("MSIE") != -1) + return true; + return false; + } + + /** + * handy routine to check if client is cartman based on hidden http input + * set using cartman JS. (no other way to tell) + */ + private static String CMMF_RESPONSE = "cmmfResponse"; + + public static boolean doCMMFResponse(IArgBlock httpParams) { + if (httpParams.getValueAsBoolean(CMMF_RESPONSE, false)) + return true; + else + return false; + } + + private static final String IMPORT_CERT = "importCert"; + private static final String IMPORT_CHAIN = "importCAChain"; + private static final String IMPORT_CERT_MIME_TYPE = "importCertMimeType"; + // default mime type + private static final String NS_X509_USER_CERT = "application/x-x509-user-cert"; + private static final String NS_X509_EMAIL_CERT = "application/x-x509-email-cert"; + + // CMC mime types + public static final String SIMPLE_ENROLLMENT_REQUEST = "application/pkcs10"; + public static final String SIMPLE_ENROLLMENT_RESPONSE = "application/pkcs7-mime"; + public static final String FULL_ENROLLMENT_REQUEST = "application/pkcs7-mime"; + public static final String FULL_ENROLLMENT_RESPONSE = "application/pkcs7-mime"; + + /** + * handy routine to check if client want full enrollment response + */ + public static String FULL_RESPONSE = "fullResponse"; + + public static boolean doFullResponse(IArgBlock httpParams) { + if (httpParams.getValueAsBoolean(FULL_RESPONSE, false)) + return true; + else + return false; + } + + /** + * @return false if import cert directly set to false. + * @return true if import cert directly is true and import cert. + */ + protected boolean checkImportCertToNav( + HttpServletResponse httpResp, IArgBlock httpParams, X509CertImpl cert) + throws EBaseException { + if (!httpParams.getValueAsBoolean(IMPORT_CERT, false)) { + return false; + } + boolean importCAChain = + httpParams.getValueAsBoolean(IMPORT_CHAIN, true); + // XXX Temporary workaround because of problem with passing Mime type + boolean emailCert = + httpParams.getValueAsBoolean("emailCert", false); + String importMimeType = (emailCert) ? + httpParams.getValueAsString(IMPORT_CERT_MIME_TYPE, NS_X509_EMAIL_CERT) : + httpParams.getValueAsString(IMPORT_CERT_MIME_TYPE, NS_X509_USER_CERT); + + // String importMimeType = + // httpParams.getValueAsString( + // IMPORT_CERT_MIME_TYPE, NS_X509_USER_CERT); + importCertToNav(httpResp, cert, importMimeType, importCAChain); + return true; + } + + /** + * handy routine to import cert to old navigator in nav mime type. + */ + public void importCertToNav( + HttpServletResponse httpResp, X509CertImpl cert, + String contentType, boolean importCAChain) + throws EBaseException { + ServletOutputStream out = null; + byte[] encoding = null; + + CMS.debug("CMSServlet: importCertToNav " + + "contentType=" + contentType + " " + + "importCAChain=" + importCAChain); + try { + out = httpResp.getOutputStream(); + // CA chain. + if (importCAChain) { + CertificateChain caChain = null; + X509Certificate[] caCerts = null; + PKCS7 p7 = null; + + caChain = ((ICertAuthority) mAuthority).getCACertChain(); + caCerts = caChain.getChain(); + + // set user + CA cert chain in pkcs7 + X509CertImpl[] userChain = + new X509CertImpl[caCerts.length + 1]; + + userChain[0] = cert; + int m = 1, n = 0; + + for (; n < caCerts.length; m++, n++) { + userChain[m] = (X509CertImpl) caCerts[n]; + + /* + System.out.println( + m+"th Cert "+userChain[m].toString()); + */ + } + p7 = new PKCS7(new AlgorithmId[0], + new ContentInfo(new byte[0]), + userChain, + new SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + p7.encodeSignedData(bos, false); + encoding = bos.toByteArray(); + CMS.debug("CMServlet: return P7 " + CMS.BtoA(encoding)); + } else { + encoding = cert.getEncoded(); + CMS.debug("CMServlet: return Certificate " + CMS.BtoA(encoding)); + } + httpResp.setContentType(contentType); + out.write(encoding); + } catch (IOException e) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_RET_CERT_IMPORT_ERR", e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_RETURNING_CERT")); + } catch (CertificateEncodingException e) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_ENCODED_IMP_CERT", e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT")); + } + } + + protected static void saveAuthToken(IAuthToken token, IRequest req) { + if (token != null && req != null) + req.setExtData(IRequest.AUTH_TOKEN, token); + + // # 56230 - expose auth token parameters to the policy predicate + if (token != null && req != null) { + Enumeration<String> e = token.getElements(); + while (e.hasMoreElements()) { + String n = e.nextElement(); + String[] x1 = token.getInStringArray(n); + if (x1 != null) { + for (int i = 0; i < x1.length; i++) { + CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + + "(" + i + ")=" + x1[i]); + req.setExtData(IRequest.AUTH_TOKEN + "-" + n + "(" + i + ")", + x1[i]); + } + } else { + String x = token.getInString(n); + if (x != null) { + CMS.debug("Setting " + IRequest.AUTH_TOKEN + "-" + n + "=" + x); + req.setExtData(IRequest.AUTH_TOKEN + "-" + n, x); + } + } + } // while + } // if + } + + protected IAuthToken getAuthToken(IRequest req) { + return req.getExtDataInAuthToken(IRequest.AUTH_TOKEN); + } + + protected static boolean connectionIsSSL(HttpServletRequest httpReq) { + return httpReq.isSecure(); + } + + /** + * handy routine for getting agent's relative path + */ + protected String getRelPath(IAuthority authority) { + if (authority instanceof ICertificateAuthority) + return "ca/"; + else if (authority instanceof IRegistrationAuthority) + return "ra/"; + else if (authority instanceof IKeyRecoveryAuthority) + return "kra/"; + else + return "/"; + } + + /** + * A system certificate such as the CA signing certificate + * should not be allowed to delete. + * The main purpose is to avoid revoking the self signed + * CA certificate accidentially. + */ + protected boolean isSystemCertificate(BigInteger serialNo) { + if (!(mAuthority instanceof ICertificateAuthority)) { + return false; + } + X509Certificate caCert = + ((ICertificateAuthority) mAuthority).getCACert(); + if (caCert != null) { + /* only check this if we are self-signed */ + if (caCert.getSubjectDN().equals(caCert.getIssuerDN())) { + if (caCert.getSerialNumber().equals(serialNo)) { + return true; + } + } + } + return false; + } + + /** + * make a CRL entry from a serial number and revocation reason. + * + * @return a RevokedCertImpl that can be entered in a CRL. + */ + protected RevokedCertImpl formCRLEntry( + BigInteger serialNo, RevocationReason reason) + throws EBaseException { + CRLReasonExtension reasonExt = new CRLReasonExtension(reason); + CRLExtensions crlentryexts = new CRLExtensions(); + + try { + crlentryexts.set(CRLReasonExtension.NAME, reasonExt); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_CRL_REASON", reason.toString(), e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_SETTING_CRLREASON")); + } + RevokedCertImpl crlentry = + new RevokedCertImpl(serialNo, CMS.getCurrentDate(), crlentryexts); + + return crlentry; + } + + /** + * check if a certificate (serial number) is revoked on a CA. + * + * @return true if cert is marked revoked in the CA's database. + * @return false if cert is not marked revoked. + */ + protected boolean certIsRevoked(BigInteger serialNum) + throws EBaseException { + ICertRecord certRecord = getCertRecord(serialNum); + + if (certRecord == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_BAD_CERT_SER_NUM", String.valueOf(serialNum))); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_INVALID_CERT")); + } + if (certRecord.getStatus().equals(ICertRecord.STATUS_REVOKED)) + return true; + return false; + } + + public static String generateSalt() { + Random rnd = new Random(); + String salt = new Integer(rnd.nextInt()).toString(); + return salt; + } + + protected String hashPassword(String pwd) { + String salt = generateSalt(); + byte[] pwdDigest = mSHADigest.digest((salt + pwd).getBytes()); + String b64E = Utils.base64encode(pwdDigest); + + return "{SHA}" + salt + ";" + b64E; + } + + /** + * @param req http servlet request + * @param realpathFile the file to get. + * @param locale array of at least one to be filled with locale found. + */ + public static File getLangFile( + HttpServletRequest req, File realpathFile, Locale[] locale) + throws IOException { + File file = null; + String acceptLang = req.getHeader("accept-language"); + + if (acceptLang != null && !acceptLang.equals("")) { + StringTokenizer tokenizer = new StringTokenizer(acceptLang, ","); + int numLangs = tokenizer.countTokens(); + + if (numLangs > 0) { + // languages are searched in order. + String parent = realpathFile.getParent(); + + if (parent == null) { + parent = "." + File.separatorChar; + } + String name = realpathFile.getName(); + + if (name == null) { // filename should never be null. + throw new IOException("file has no name"); + } + int i; + + for (i = 0; i < numLangs; i++) { + String lang = null; + String token = tokenizer.nextToken(); + + int semicolon = token.indexOf(';'); + + if (semicolon == -1) { + lang = token.trim(); + } else { + if (semicolon < 2) + continue; // protocol error. + lang = token.substring(0, semicolon).trim(); + } + // if browser locale is the same as default locale, + // use the default form. (is this the right thing to do ?) + Locale l = getLocale(lang); + + if (Locale.getDefault().equals(l)) { + locale[0] = l; + file = realpathFile; + break; + } + + String langfilepath = + parent + File.separatorChar + + lang + File.separatorChar + name; + + file = new File(langfilepath); + if (file.exists()) { + locale[0] = getLocale(lang); + break; + } + } + // if no file for lang was found use default + if (i == numLangs) { + file = realpathFile; + locale[0] = Locale.getDefault(); + } + } + } else { + // use default if accept-language is not availabe + file = realpathFile; + locale[0] = Locale.getDefault(); + } + return file; + } + + public static Locale getLocale(String lang) { + int dash = lang.indexOf('-'); + + if (dash == -1) + return new Locale(lang, ""); + else + return new Locale(lang.substring(0, dash), lang.substring(dash + 1)); + } + + public IAuthToken authenticate(CMSRequest req) + throws EBaseException { + return authenticate(req, mAuthMgr); + } + + public IAuthToken authenticate(HttpServletRequest httpReq) + throws EBaseException { + return authenticate(httpReq, mAuthMgr); + } + + public IAuthToken authenticate(CMSRequest req, String authMgrName) + throws EBaseException { + IAuthToken authToken = authenticate(req.getHttpReq(), + authMgrName); + + saveAuthToken(authToken, req.getIRequest()); + return authToken; + } + + /** + * Authentication + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_FAIL used when authentication fails (in case of SSL-client auth, only + * webserver env can pick up the SSL violation; CS authMgr can pick up cert mis-match, so this event is used) + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTH_SUCCESS used when authentication succeeded + * </ul> + * + * @exception EBaseException an error has occurred + */ + public IAuthToken authenticate(HttpServletRequest httpReq, String authMgrName) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = ILogger.UNIDENTIFIED; + String auditAuthMgrID = ILogger.UNIDENTIFIED; + String auditUID = ILogger.UNIDENTIFIED; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + String getClientCert = mGetClientCert; + + IArgBlock httpArgs = CMS.createArgBlock(toHashtable(httpReq)); + SessionContext ctx = SessionContext.getContext(); + String ip = httpReq.getRemoteAddr(); + CMS.debug("IP: " + ip); + + if (ip != null) { + ctx.put(SessionContext.IPADDRESS, ip); + } + if (authMgrName != null) { + CMS.debug("AuthMgrName: " + authMgrName); + ctx.put(SessionContext.AUTH_MANAGER_ID, authMgrName); + } + // put locale into session context + ctx.put(SessionContext.LOCALE, getLocale(httpReq)); + + // + // check ssl client authentication if specified. + // + X509Certificate clientCert = null; + + if (getClientCert != null && getClientCert.equals("true")) { + CMS.debug("CMSServlet: retrieving SSL certificate"); + clientCert = getSSLClientCertificate(httpReq); + } + + // + // check authentication by auth manager if any. + // + if (authMgrName == null) { + + // Fixed Blackflag Bug #613900: Since this code block does + // NOT actually constitute an authentication failure, but + // rather the case in which a given servlet has been correctly + // configured to NOT require an authentication manager, the + // audit message called LOGGING_SIGNED_AUDIT_AUTH_FAIL has + // been removed. + + CMS.debug("CMSServlet: no authMgrName"); + return null; + } else { + // save the "Subject DN" of this certificate in case it + // must be audited as an authentication failure + if (clientCert == null) { + CMS.debug("CMSServlet: no client certificate found"); + } else { + String certUID = clientCert.getSubjectDN().getName(); + CMS.debug("CMSServlet: certUID=" + certUID); + + if (certUID != null) { + certUID = certUID.trim(); + + if (!(certUID.equals(""))) { + // reset the "auditUID" + auditUID = certUID; + } + } + } + + // reset the "auditAuthMgrID" + auditAuthMgrID = authMgrName; + } + AuthToken authToken = CMSGateway.checkAuthManager(httpReq, + httpArgs, + clientCert, + authMgrName); + if (authToken == null) { + return null; + } + String userid = authToken.getInString(IAuthToken.USER_ID); + + CMS.debug("CMSServlet: userid=" + userid); + + if (userid != null) { + ctx.put(SessionContext.USER_ID, userid); + } + + // reset the "auditSubjectID" + auditSubjectID = auditSubjectID(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditAuthMgrID); + + audit(auditMessage); + + return authToken; + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditAuthMgrID, + auditUID); + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } + } + + public AuthzToken authorize(String authzMgrName, String resource, IAuthToken authToken, + String exp) throws EBaseException { + AuthzToken authzToken = null; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditGroupID = auditGroupID(); + String auditACLResource = resource; + String auditOperation = "enroll"; + + try { + authzToken = mAuthz.authorize(authzMgrName, authToken, exp); + if (authzToken != null) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.SUCCESS, + auditGroupID); + + audit(auditMessage); + } else { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroupID); + + audit(auditMessage); + } + return authzToken; + } catch (Exception e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroupID); + + audit(auditMessage); + throw new EBaseException(e.toString()); + } + } + + /** + * Authorize must occur after Authenticate + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_FAIL used when authorization has failed + * <li>signed.audit LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS used when authorization is successful + * <li>signed.audit LOGGING_SIGNED_AUDIT_ROLE_ASSUME used when user assumes a role (in current CS that's when one + * accesses a role port) + * </ul> + * + * @param authzMgrName string representing the name of the authorization + * manager + * @param authToken the authentication token + * @param resource a string representing the ACL resource id as defined in + * the ACL resource list + * @param operation a string representing one of the operations as defined + * within the ACL statement (e. g. - "read" for an ACL statement containing + * "(read,write)") + * @exception EBaseException an error has occurred + * @return the authorization token + */ + public AuthzToken authorize(String authzMgrName, IAuthToken authToken, + String resource, String operation) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditGroupID = auditGroupID(); + String auditID = auditSubjectID; + String auditACLResource = resource; + String auditOperation = operation; + + SessionContext auditContext = SessionContext.getExistingContext(); + String authManagerId = null; + + if (auditContext != null) { + authManagerId = (String) auditContext.get(SessionContext.AUTH_MANAGER_ID); + + if (authManagerId != null && authManagerId.equals("TokenAuth")) { + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + CMS.debug("CMSServlet: in authorize... TokenAuth auditSubjectID unavailable, changing to auditGroupID"); + auditID = auditGroupID; + } + } + } + + // "normalize" the "auditACLResource" value + if (auditACLResource != null) { + auditACLResource = auditACLResource.trim(); + } + + // "normalize" the "auditOperation" value + if (auditOperation != null) { + auditOperation = auditOperation.trim(); + } + + if (authzMgrName == null) { + // Fixed Blackflag Bug #613900: Since this code block does + // NOT actually constitute an authorization failure, but + // rather the case in which a given servlet has been correctly + // configured to NOT require an authorization manager, the + // audit message called LOGGING_SIGNED_AUDIT_AUTHZ_FAIL and + // the audit message called LOGGING_SIGNED_AUDIT_ROLE_ASSUME + // (marked as a failure) have been removed. + + return null; + } + + try { + AuthzToken authzTok = mAuthz.authorize(authzMgrName, + authToken, + resource, + operation); + + if (authzTok != null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.SUCCESS, + auditGroups(auditSubjectID)); + + audit(auditMessage); + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + } + + return authzTok; + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return null; + } catch (Exception eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTHZ_FAIL, + auditSubjectID, + ILogger.FAILURE, + auditACLResource, + auditOperation); + + audit(auditMessage); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + auditSubjectID, + ILogger.FAILURE, + auditGroups(auditSubjectID)); + + audit(auditMessage); + + return null; + } + } + + /** + * Signed Audit Log + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to store messages to the signed audit log. + * <P> + * + * @param msg signed audit log message + */ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (mSignedAuditLogger == null) { + return; + } + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Subject ID + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to obtain the "SubjectID" for + * a signed audit log message. + * <P> + * + * @return id string containing the signed audit log message SubjectID + */ + protected String auditSubjectID() { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + CMS.debug("CMSServlet: in auditSubjectID"); + String subjectID = null; + + // Initialize subjectID + SessionContext auditContext = SessionContext.getExistingContext(); + + CMS.debug("CMSServlet: auditSubjectID auditContext " + auditContext); + if (auditContext != null) { + subjectID = (String) + auditContext.get(SessionContext.USER_ID); + + CMS.debug("CMSServlet auditSubjectID: subjectID: " + subjectID); + if (subjectID != null) { + subjectID = subjectID.trim(); + } else { + subjectID = ILogger.NONROLEUSER; + } + } else { + subjectID = ILogger.UNIDENTIFIED; + } + + return subjectID; + } + + /** + * Signed Audit Log Group ID + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to obtain the "gid" for + * a signed audit log message. + * <P> + * + * @return id string containing the signed audit log message SubjectID + */ + protected String auditGroupID() { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + CMS.debug("CMSServlet: in auditGroupID"); + String groupID = null; + + // Initialize groupID + SessionContext auditContext = SessionContext.getExistingContext(); + + CMS.debug("CMSServlet: auditGroupID auditContext " + auditContext); + if (auditContext != null) { + groupID = (String) + auditContext.get(SessionContext.GROUP_ID); + + CMS.debug("CMSServlet auditGroupID: groupID: " + groupID); + if (groupID != null) { + groupID = groupID.trim(); + } else { + groupID = ILogger.NONROLEUSER; + } + } else { + groupID = ILogger.UNIDENTIFIED; + } + + return groupID; + } + + /** + * Signed Audit Groups + * + * This method is called to extract all "groups" associated + * with the "auditSubjectID()". + * <P> + * + * @param SubjectID string containing the signed audit log message SubjectID + * @return a delimited string of groups associated + * with the "auditSubjectID()" + */ + private String auditGroups(String SubjectID) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + if ((SubjectID == null) || + (SubjectID.equals(ILogger.UNIDENTIFIED))) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + Enumeration<IGroup> groups = null; + + try { + groups = mUG.findGroups("*"); + } catch (Exception e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + StringBuffer membersString = new StringBuffer(); + + while (groups.hasMoreElements()) { + IGroup group = groups.nextElement(); + + if (group.isMember(SubjectID) == true) { + if (membersString.length() != 0) { + membersString.append(", "); + } + + membersString.append(group.getGroupID()); + } + } + + if (membersString.length() != 0) { + return membersString.toString(); + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } + + /** + * 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 outputResult(HttpServletResponse httpResp, + String contentType, byte[] content) { + try { + OutputStream os = httpResp.getOutputStream(); + + httpResp.setContentType(contentType); + httpResp.setContentLength(content.length); + os.write(content); + os.flush(); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); + return; + } + } + + protected void outputError(HttpServletResponse httpResp, String errorString) { + outputError(httpResp, FAILURE, errorString, null); + } + + protected void outputError(HttpServletResponse httpResp, String errorString, String requestId) { + outputError(httpResp, FAILURE, errorString, null); + } + + protected void outputError(HttpServletResponse httpResp, String status, String errorString, String requestId) { + XMLObject xmlObj = null; + try { + xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + xmlObj.addItemToContainer(root, "Status", status); + xmlObj.addItemToContainer(root, "Error", errorString); + if (requestId != null) { + xmlObj.addItemToContainer(root, "RequestId", requestId); + } + byte[] cb = xmlObj.toByteArray(); + + OutputStream os = httpResp.getOutputStream(); + httpResp.setContentType("application/xml"); + httpResp.setContentLength(cb.length); + os.write(cb); + os.flush(); + return; + } catch (Exception ee) { + CMS.debug("Failed to send XML output to the server."); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", ee.toString())); + } + } + + protected StringBuffer escapeValueRfc1779(String v, boolean doubleEscape) { + StringBuffer result = new StringBuffer(); + + // Do we need to escape any characters + for (int i = 0; i < v.length(); i++) { + int c = v.charAt(i); + if (c == ',' || c == '=' || c == '+' || c == '<' || + c == '>' || c == '#' || c == ';' || c == '\r' || + c == '\n' || c == '\\' || c == '"') { + if ((c == 0x5c) && ((i + 1) < v.length())) { + int nextC = v.charAt(i + 1); + if ((c == 0x5c) && (nextC == ',' || nextC == '=' || nextC == '+' || + nextC == '<' || nextC == '>' || nextC == '#' || + nextC == ';' || nextC == '\r' || nextC == '\n' || + nextC == '\\' || nextC == '"')) { + if (doubleEscape) + result.append('\\'); + } else { + result.append('\\'); + if (doubleEscape) + result.append('\\'); + } + } else { + result.append('\\'); + if (doubleEscape) + result.append('\\'); + } + } + if (c == '\r') { + result.append("0D"); + } else if (c == '\n') { + result.append("0A"); + } else { + result.append((char) c); + } + } + return result; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/base/CMSStartServlet.java b/base/common/src/com/netscape/cms/servlet/base/CMSStartServlet.java new file mode 100644 index 000000000..4bfc74607 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/CMSStartServlet.java @@ -0,0 +1,117 @@ +// --- 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.base; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.cmsutil.util.Utils; + +/** + * This servlet is started by the web server at startup, and + * it starts the CMS framework. + * + * @version $Revision$, $Date$ + */ +public class CMSStartServlet extends HttpServlet { + /** + * + */ + private static final long serialVersionUID = 515623839479425172L; + public final static String PROP_CMS_CFG = "cfgPath"; + + public void init(ServletConfig config) throws ServletException { + super.init(config); + String path = config.getInitParameter(PROP_CMS_CFG); + + File f = new File(path); + String old_path = ""; + if (!f.exists()) { + int index = path.lastIndexOf("CS.cfg"); + if (index != -1) { + old_path = path.substring(0, index) + "CMS.cfg"; + } + File f1 = new File(old_path); + if (f1.exists()) { + // The following block of code moves "CMS.cfg" to "CS.cfg". + try { + if (Utils.isNT()) { + // NT is very picky on the path + Utils.exec("copy " + + f1.getAbsolutePath().replace('/', '\\') + + " " + + f.getAbsolutePath().replace('/', '\\')); + } else { + // Create a copy of the original file which + // preserves the original file permissions. + Utils.exec("cp -p " + f1.getAbsolutePath() + " " + + f.getAbsolutePath()); + } + + // Remove the original file if and only if + // the backup copy was successful. + if (f.exists()) { + f1.delete(); + + // Make certain that the new file has + // the correct permissions. + if (!Utils.isNT()) { + Utils.exec("chmod 00660 " + f.getAbsolutePath()); + } + } + } catch (Exception e) { + } + } + } + try { + CMS.start(path); + } catch (EBaseException e) { + } + } + + public void doGet(HttpServletRequest req, HttpServletResponse res) + throws ServletException, IOException { + res.setContentType("text/html"); + + PrintWriter out = res.getWriter(); + + out.print("<html>"); + out.print("<head><title>CMS is started!</title></head>"); + out.print("<body>"); + out.print("<h1>CMS is started!</h1>"); + out.print("</body></html>"); + } + + public String getServletInfo() { + return "CMS startup servlet"; + } + + public void destroy() { + CMS.shutdown(); + super.destroy(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java b/base/common/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java new file mode 100644 index 000000000..54e453f30 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java @@ -0,0 +1,97 @@ +// --- 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.base; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * This is the servlet that displays the html page for the corresponding input id. + * + * @version $Revision$, $Date$ + */ +public class DisplayHtmlServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -4343458180370708327L; + public final static String PROP_TEMPLATE = "template"; + public final static String PROP_HTML_PATH = "htmlPath"; + + private String mHTMLPath = null; + + public DisplayHtmlServlet() { + super(); + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mHTMLPath = sc.getInitParameter(PROP_HTML_PATH); + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Serves HTTP request. + */ + public void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("DisplayHtmlServlet about to service "); + + authenticate(cmsReq); + + try { + String realpath = + mServletConfig.getServletContext().getRealPath("/" + mHTMLPath); + + if (realpath == null) { + mLogger.log( + ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_FIND_TEMPLATE", mHTMLPath)); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + File file = new File(realpath); + long flen = file.length(); + byte[] bin = new byte[(int) flen]; + FileInputStream ins = new FileInputStream(file); + + int len = 0; + if (ins.available() > 0) { + len = ins.read(bin); + } + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + bos.write(bin, 0, len); + bos.writeTo(cmsReq.getHttpResp().getOutputStream()); + ins.close(); + bos.close(); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_TEMPLATE", mHTMLPath, e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java b/base/common/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java new file mode 100644 index 000000000..0bf726879 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java @@ -0,0 +1,333 @@ +// --- 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.base; + +import java.io.IOException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthMgrPlugin; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; + +/** + * Return some javascript to the request which contains the list of + * dynamic data in the CMS system. + * <p> + * This allows the requestor (browser) to make decisions about what to present in the UI, depending on how CMS is + * configured + * + * @version $Revision$, $Date$ + */ +public class DynamicVariablesServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 7246774978153039460L; + public final static String PROP_ACCESS = "ServletAccess"; + public final static String PROP_AUTHMGR = "AuthMgr"; + public final static String PROP_CLIENTAUTH = "GetClientCert"; + + public final static String PROP_AUTHORITY = "authority"; + public final static String PROP_CLONING = "cloning"; + + private final static String INFO = "dynamicVariables"; + + private static final String PROP_DYNVAR = "dynamicVariables"; + private static final String PROP_CRLURL = "cloneMasterCrlUrl"; + private static final String VAR_SERVERDATE_STRING = "serverdate()"; + private static final Integer VAR_SERVERDATE = Integer.valueOf(1); + + private static final String VAR_SUBSYSTEMNAME_STRING = "subsystemname()"; + private static final Integer VAR_SUBSYSTEMNAME = Integer.valueOf(2); + private String VAR_SUBSYSTEMNAME_VALUE = null; + + private static final String VAR_HTTP_STRING = "http()"; + private static final Integer VAR_HTTP = Integer.valueOf(3); + private String VAR_HTTP_VALUE = null; + + private static final String VAR_AUTHMGRS_STRING = "authmgrs()"; + private static final Integer VAR_AUTHMGRS = Integer.valueOf(4); + private String VAR_AUTHMGRS_VALUE = null; + + private static final String VAR_CLA_CRL_URL_STRING = "clacrlurl()"; + private static final Integer VAR_CLA_CRL_URL = Integer.valueOf(6); + private String VAR_CLA_CRL_URL_VALUE = null; + + private String mAuthMgrCacheString = ""; + private long mAuthMgrCacheTime = 0; + private final int AUTHMGRCACHE = 10; //number of seconds to cache list of + // authmanagers for + private Hashtable<Integer, String> dynvars = null; + private String mGetClientCert = "false"; + private String mAuthMgr = null; + + private ServletConfig mServletCfg = null; + private ServletContext mServletCtx = null; + private static String mCrlurl = ""; + static { + IConfigStore config = CMS.getConfigStore().getSubStore(PROP_CLONING); + + try { + mCrlurl = + config.getString(PROP_CRLURL, ""); + } catch (EBaseException e) { + } + } + + public DynamicVariablesServlet() { + super(); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Reads the following variables from the servlet config: + * <ul> + * <li><strong>AuthMgr</strong> - the authentication manager to use to authenticate the request + * <li><strong>GetClientCert</strong> - whether to request client auth for this request + * <li><strong>authority</strong> - the authority (ca, ra, drm) to return to the client + * <li><strong>dynamicVariables</strong> - a string of the form: + * serverdate=serverdate(),subsystemname=subsystemname(), http=http(),authmgrs=authmgrs(),clacrlurl=clacrlurl() + * </ul> + * The dynamicVariables string is parsed by splitting on commas. + * When services, the HTTP request provides a piece of javascript + * code as follows. + * <p> + * Each sub expression "lhs=rhs()" forms a javascript statement of the form <i>lhs=xxx;</i> Where lhs is xxx is the + * result of 'evaluating' the rhs. The possible values for the rhs() function are: + * <ul> + * <li><strong>serverdate()</strong> - the timestamp of the server (used to ensure that the client clock is set + * correctly) + * <li><strong>subsystemname()</strong> + * <li><strong>http()</strong> - "true" or "false" - is this an http connection (as opposed to https) + * <li>authmgrs() - a comma separated list of authentication managers + * <li>clacrlurl() - the URL to get the CRL from, in the case of a Clone CA. This is defined in the CMS + * configuration parameter 'cloning.cloneMasterCrlUrl' + * </ul> + * + * @see javax.servlet.Servlet#init(ServletConfig) + */ + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthMgr = sc.getInitParameter(PROP_AUTHMGR); + mGetClientCert = sc.getInitParameter(PROP_CLIENTAUTH); + mServletCfg = sc; + + mServletCtx = sc.getServletContext(); + + VAR_SUBSYSTEMNAME_VALUE = sc.getInitParameter(PROP_AUTHORITY); + + try { + String dynvarconfig = sc.getInitParameter(PROP_DYNVAR); + StringTokenizer s = new StringTokenizer(dynvarconfig, ","); + + dynvars = new Hashtable<Integer, String>(); + + while (s.hasMoreTokens()) { + String token = s.nextToken(); + + int i = token.indexOf('='); + String varname = token.substring(0, i); + String varvalue = token.substring(i + 1); + + Integer varcode = null; + + if (varvalue.equalsIgnoreCase(VAR_SERVERDATE_STRING)) { + varcode = VAR_SERVERDATE; + } else if (varvalue.equalsIgnoreCase(VAR_SUBSYSTEMNAME_STRING)) { + varcode = VAR_SUBSYSTEMNAME; + } else if (varvalue.equalsIgnoreCase(VAR_HTTP_STRING)) { + varcode = VAR_HTTP; + } else if (varvalue.equalsIgnoreCase(VAR_AUTHMGRS_STRING)) { + varcode = VAR_AUTHMGRS; + } else if (varvalue.equalsIgnoreCase(VAR_CLA_CRL_URL_STRING)) { + varcode = VAR_CLA_CRL_URL; + } else { + throw new ServletException("bad configuration parameter in " + PROP_DYNVAR); + } + if (varcode != null) { + dynvars.put(varcode, varname); + } + } + } catch (Exception e) { + dynvars = null; + } + } + + public void service(HttpServletRequest httpReq, + HttpServletResponse httpResp) + throws ServletException, IOException { + boolean running_state = CMS.isInRunningState(); + + if (!running_state) + throw new IOException( + "CMS server is not ready to serve."); + + if (mAuthMgr != null) { + try { + authenticate(httpReq); + } catch (EBaseException e) { + mServletCtx.log(CMS.getLogMessage("CMSGW_FILE_NO_ACCESS", e.toString())); + httpResp.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + } + + httpResp.setContentType("application/x-javascript"); + httpResp.setHeader("Pragma", "no-cache"); + + try { + ServletOutputStream os = httpResp.getOutputStream(); + + if (os != null) { + if (dynvars != null) { + Enumeration<Integer> k = dynvars.keys(); + + while (k.hasMoreElements()) { + String toBeWritten; + Integer varcode = k.nextElement(); + + if (varcode.equals(VAR_SERVERDATE)) { + toBeWritten = dynvars.get(varcode) + + "=" + + getServerDate() + + ";\n"; + + os.print(toBeWritten); + } + + if (varcode.equals(VAR_SUBSYSTEMNAME)) { + if (getSubsystemName() != null) { + toBeWritten = dynvars.get(varcode) + + "=" + "\"" + + getSubsystemName() + "\"" + + ";\n"; + os.print(toBeWritten); + } + } + + if (varcode.equals(VAR_HTTP)) { + if (getHttp(httpReq) != null) { + toBeWritten = dynvars.get(varcode) + + "=" + "\"" + + getHttp(httpReq) + "\"" + + ";\n"; + os.print(toBeWritten); + } + } + + if (varcode.equals(VAR_CLA_CRL_URL)) { + if (getImportCrlUrl() != null) { + toBeWritten = dynvars.get(varcode) + + "=" + "\"" + + getImportCrlUrl() + "\"" + + ";\n"; + os.print(toBeWritten); + } + } + + if (varcode.equals(VAR_AUTHMGRS)) { + toBeWritten = ""; + IAuthSubsystem as = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + Enumeration<IAuthManager> ame = as.getAuthManagers(); + + Date d = CMS.getCurrentDate(); + long now = d.getTime(); + + if (now > (mAuthMgrCacheTime + 1000 * AUTHMGRCACHE)) { + int i = 0; + + StringBuffer sb = new StringBuffer(); + while (ame.hasMoreElements()) { + IAuthManager am = ame.nextElement(); + String amName = am.getImplName(); + + AuthMgrPlugin ap = as.getAuthManagerPluginImpl(amName); + + if (ap.isVisible()) { + sb.append("authmanager["); + sb.append(i); + sb.append("]=\""); + sb.append(amName); + sb.append("\";\n"); + i++; + } + } + toBeWritten = sb.toString(); + mAuthMgrCacheString = toBeWritten; + mAuthMgrCacheTime = now; + } else { + toBeWritten = mAuthMgrCacheString; + } + if (toBeWritten.length() != 0) { + os.print("authmanager = new Array();\n"); + os.print(toBeWritten); + } + } + + } + } + os.close(); + } + + } catch (IOException e) { + throw new ServletException("couldn't get outputstream"); + } + } + + private String getServerDate() { + Date d = new Date(); + String now = Long.toString(d.getTime()); + + return now; + } + + private String getSubsystemName() { + return VAR_SUBSYSTEMNAME_VALUE; + } + + private String getHttp(HttpServletRequest httpReq) { + if (httpReq.isSecure()) + return "false"; + else + return "true"; + } + + private String getImportCrlUrl() { + return mCrlurl; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/GetStats.java b/base/common/src/com/netscape/cms/servlet/base/GetStats.java new file mode 100644 index 000000000..c21b56835 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/GetStats.java @@ -0,0 +1,184 @@ +// --- 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.base; + +import java.io.IOException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.certsrv.util.StatsEvent; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve information. + * + * @version $Revision$, $Date$ + */ +public class GetStats extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -3336253558044271816L; + private final static String TPL_FILE = "getStats.template"; + private String mFormPath = null; + + public GetStats() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template + * file "getOCSPInfo.template" to render the result page. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + // coming from agent + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + StatsEvent st = statsSub.getMainStatsEvent(); + + String op = httpReq.getParameter("op"); + if (op != null && op.equals("clear")) { + statsSub.resetCounters(); + } + + header.addStringValue("startTime", statsSub.getStartTime().toString()); + header.addStringValue("curTime", (new Date()).toString()); + parse(argSet, st, 0); + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + public String getSep(int level) { + StringBuffer s = new StringBuffer(); + for (int i = 0; i < level; i++) { + s.append("-"); + } + return s.toString(); + } + + public void parse(CMSTemplateParams argSet, StatsEvent st, int level) { + Enumeration<String> names = st.getSubEventNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + StatsEvent subSt = st.getSubEvent(name); + + IArgBlock rarg = CMS.createArgBlock(); + rarg.addStringValue("name", getSep(level) + " " + subSt.getName()); + rarg.addLongValue("noOfOp", subSt.getNoOfOperations()); + rarg.addLongValue("timeTaken", subSt.getTimeTaken()); + rarg.addLongValue("max", subSt.getMax()); + rarg.addLongValue("min", subSt.getMin()); + rarg.addLongValue("percentage", subSt.getPercentage()); + rarg.addLongValue("avg", subSt.getAvg()); + rarg.addLongValue("stddev", subSt.getStdDev()); + argSet.addRepeatRecord(rarg); + + parse(argSet, subSt, level + 1); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/IndexServlet.java b/base/common/src/com/netscape/cms/servlet/base/IndexServlet.java new file mode 100644 index 000000000..95dbf2abf --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/IndexServlet.java @@ -0,0 +1,118 @@ +// --- 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.base; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.common.CMSGateway; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.IndexTemplateFiller; + +/** + * This is the servlet that builds the index page in + * various ports. + * + * @version $Revision$, $Date$ + */ +public class IndexServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -8632685610380549L; + + public final static String PROP_TEMPLATE = "template"; + + private final static String INFO = "indexServlet"; + + // input parameters + + // output parameters + private final static String OUT_TYPE = "type"; + private final static String OUT_ID = "id"; + private final static String OUT_TOTAL_COUNT = "totalCount"; + private final static String OUT_ERROR = "errorDetails"; + + private String mTemplateName = null; + + public IndexServlet() { + super(); + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mTemplateName = sc.getInitParameter(PROP_TEMPLATE); + + /* + mTemplates.put(CMSRequest.SUCCESS, + new CMSLoadTemplate( + PROP_SUCCESS_TEMPLATE, PROP_SUCCESS_TEMPLATE_FILLER, + mTemplateName, new IndexTemplateFiller())); + */ + mTemplates.remove(CMSRequest.SUCCESS); + } + + public CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP request. + */ + public void process(CMSRequest cmsReq) throws EBaseException { + if (CMSGateway.getEnableAdminEnroll() && + mAuthority != null && + mAuthority instanceof ICertificateAuthority) { + try { + cmsReq.getHttpResp().sendRedirect("/ca/adminEnroll.html"); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAIL_REDIRECT_ADMIN_ENROLL", e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_REDIRECTING_ADMINENROLL1", + e.toString())); + } + return; + } else { + try { + renderTemplate( + cmsReq, mTemplateName, new IndexTemplateFiller()); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAIL_RENDER_TEMPLATE", mTemplateName, e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSG_ERROR_DISPLAY_TEMPLATE")); + } + } + cmsReq.setStatus(CMSRequest.SUCCESS); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/PortsServlet.java b/base/common/src/com/netscape/cms/servlet/base/PortsServlet.java new file mode 100644 index 000000000..fced583a2 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/PortsServlet.java @@ -0,0 +1,90 @@ +// --- 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.base; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.xml.XMLObject; + +/** + * This servlet returns port information. + * + * @version $Revision$, $Date$ + */ +public class PortsServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -3750153734073658934L; + private final static String INFO = "ports"; + + public PortsServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override these to output directly ourselves. + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + } + + /** + * Serves HTTP request. + */ + public void process(CMSRequest cmsReq) throws EBaseException { + // process query if authentication is successful + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + String secure = req.getParameter("secure"); + String port = null; + + if (secure.equals("true")) + port = CMS.getEESSLPort(); + else + port = CMS.getEENonSSLPort(); + + try { + XMLObject xmlObj = null; + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("XMLResponse"); + xmlObj.addItemToContainer(root, "Status", SUCCESS); + xmlObj.addItemToContainer(root, "Port", port); + byte[] cb = xmlObj.toByteArray(); + outputResult(resp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + protected void renderResult(CMSRequest cmsReq) throws IOException { + // do nothing, ie, it will not return the default javascript. + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/ProxyServlet.java b/base/common/src/com/netscape/cms/servlet/base/ProxyServlet.java new file mode 100644 index 000000000..41666ab31 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/ProxyServlet.java @@ -0,0 +1,248 @@ +/* CMS_SDK_LICENSE_TEXT */ + +package com.netscape.cms.servlet.base; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; + +/** + * This is a servlet that proxies request to another servlet. + * + * SERVLET REDIRECTION + * Specify the URL of a servlet to forward the request to + * destServlet: /ee/ca/newservlet + * + * PARAMETER MAPPING + * In the servlet configuration (as an init-param in web.xml) you + * can optionally specify a value for the parameter 'parameterMap' + * which contains a list of HTTP parameters which should be + * translated to new names. + * + * parameterMap: name1->newname1,name2->newname2 + * + * Optionally, names can be set to static values: + * + * parameterMap: name1->name2=value + * + * Examples: + * Consider the following HTTP input parameters: + * vehicle:car make:ford model:explorer + * + * The following config strings will have this effect: + * parameterMap: make->manufacturer,model->name=expedition,->suv=true + * output: vehicle:car manufactuer:ford model:expedition suv:true + * + * @version $Revision$, $Date$ + */ +public class ProxyServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = -2535349161521094539L; + private String mDest = null; + private String mDestContext = null; + private String mSrcContext = null; + private String mAppendPathInfo = null; + private Vector<String> mMatchStrings = new Vector<String>(); + private String mDestServletOnNoMatch = null; + private String mAppendPathInfoOnNoMatch = null; + private Map<String, String> mParamMap = new HashMap<String, String>(); + private Map<String, String[]> mParamValue = new HashMap<String, String[]>(); + + public ProxyServlet() { + } + + private void parseParamTable(String s) { + if (s == null) + return; + + String[] params = s.split(","); + for (int i = 0; i < params.length; i++) { + String p = params[i]; + if (p != null) { + String[] paramNames = p.split("->"); + if (paramNames.length != 2) { + } + String from = paramNames[0]; + String to = paramNames[1]; + if (from != null && to != null) { + String[] splitTo = to.split("="); + String toName = splitTo[0]; + if (from.length() > 0) { + mParamMap.put(from, toName); + } + if (splitTo.length == 2) { + String toValue = splitTo[1]; + String toValues[] = new String[1]; + toValues[0] = toValue; + mParamValue.put(toName, toValues); + } + } + } + } + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + String mMatchStrs = sc.getInitParameter("matchURIStrings"); + if (mMatchStrs != null && (!mMatchStrs.equals(""))) { + StringTokenizer st = new StringTokenizer(mMatchStrs, ","); + while (st.hasMoreTokens()) { + mMatchStrings.addElement(st.nextToken()); + } + } + mDestServletOnNoMatch = sc.getInitParameter("destServletOnNoMatch"); + mDestContext = sc.getInitParameter("destContext"); + mDest = sc.getInitParameter("destServlet"); + mSrcContext = sc.getInitParameter("srcContext"); + mAppendPathInfo = sc.getInitParameter("appendPathInfo"); + mAppendPathInfoOnNoMatch = sc.getInitParameter("appendPathInfoOnNoMatch"); + String map = sc.getInitParameter("parameterMap"); + if (map != null) { + parseParamTable(map); + } + } + + public void service(HttpServletRequest req, HttpServletResponse res) throws + IOException, ServletException { + RequestDispatcher dispatcher = null; + String dest = mDest; + String uri = req.getRequestURI(); + + // check if match strings are specified. If it is, we need + // to deal with the alternate dest + if (mMatchStrings.size() != 0) { + boolean matched = false; + for (int i = 0; i < mMatchStrings.size(); i++) { + String t = mMatchStrings.elementAt(i); + if (uri.indexOf(t) != -1) { + matched = true; + } + } + if (!matched) { + dest = mDestServletOnNoMatch; + // append Path info for OCSP request in Get method + if (mAppendPathInfoOnNoMatch != null && + !mAppendPathInfoOnNoMatch.equals("")) { + dest = dest + uri.replace(mAppendPathInfoOnNoMatch, ""); + } + } + } + if (dest == null || dest.equals("")) { + // mapping everything + dest = uri; + dest = dest.replaceFirst(mSrcContext, ""); + } + if (mAppendPathInfo != null && !mAppendPathInfo.equals("")) { + dest = dest + uri.replace(mAppendPathInfo, ""); + } + if (mDestContext != null && !mDestContext.equals("")) { + dispatcher = getServletContext().getContext(mDestContext).getRequestDispatcher(dest); + } else { + dispatcher = req.getRequestDispatcher(dest); + } + + // If a parameter map was specified + if (mParamMap != null && !mParamMap.isEmpty()) { + // Make a new wrapper with the new parameters + ProxyWrapper r = new ProxyWrapper(req); + r.setParameterMapAndValue(mParamMap, mParamValue); + req = r; + } + + dispatcher.forward(req, res); + } +} + +class ProxyWrapper extends HttpServletRequestWrapper { + private Map<String, String> mMap = null; + private Map<String, String[]> mValueMap = null; + + public ProxyWrapper(HttpServletRequest req) { + super(req); + } + + public void setParameterMapAndValue(Map<String, String> m, Map<String, String[]> v) { + if (m != null) + mMap = m; + if (v != null) + mValueMap = v; + } + + @SuppressWarnings("unchecked") + public Map<String, String[]> getParameterMap() { + try { + // If we haven't specified any parameter mapping, just + // use the regular implementation + if (mMap == null) + return super.getParameterMap(); + else { + // Make a new Map for us to put stuff in + Map<String, String[]> n = new HashMap<String, String[]>(); + // get the HTTP parameters the user supplied. + Map<String, String[]> m = super.getParameterMap(); + Set<Map.Entry<String, String[]>> s = m.entrySet(); + Iterator<Map.Entry<String, String[]>> i = s.iterator(); + while (i.hasNext()) { + Map.Entry<String, String[]> me = i.next(); + String name = me.getKey(); + String[] values = me.getValue(); + String newname = null; + if (name != null) { + newname = (String) mMap.get(name); + } + + // No mapping specified, just use existing name/value + if (newname == null || mValueMap == null) { + n.put(name, values); + } else { // new name specified + Object o = mValueMap.get(newname); + // check if new (static) value specified + if (o == null) { + n.put(newname, values); + } else { + String newvalues[] = (String[]) mValueMap.get(newname); + n.put(newname, newvalues); + } + } + } + // Now, deal with static values set in the config + // which weren't set in the HTTP request + Set<Map.Entry<String, String[]>> s2 = mValueMap.entrySet(); + Iterator<Map.Entry<String, String[]>> i2 = s2.iterator(); + // Cycle through all the static values + while (i2.hasNext()) { + Map.Entry<String, String[]> me2 = i2.next(); + String name2 = me2.getKey(); + if (n.get(name2) == null) { + String[] values2 = me2.getValue(); + // If the parameter is not set in the map + // Set it now + n.put(name2, values2); + } + } + + return n; + } + } catch (NullPointerException npe) { + CMS.debug(npe); + return null; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/SystemInfoServlet.java b/base/common/src/com/netscape/cms/servlet/base/SystemInfoServlet.java new file mode 100644 index 000000000..f883fd373 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/SystemInfoServlet.java @@ -0,0 +1,287 @@ +// --- 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.base; + +import java.io.IOException; +import java.util.Date; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; + +/** + * Displays detailed information about java VM internals, including + * current JVM memory usage, and detailed information about each + * thread. + * <p> + * Also allows user to trigger a new garbage collection + * + * @version $Revision$, $Date$ + */ +public class SystemInfoServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = -438134935001530607L; + + public SystemInfoServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + } + + /** + * service the request, returning HTML to the client. + * This method has different behaviour depending on the + * value of the 'op' HTTP parameter. + * <UL> + * <LI>op = <i>undefined</i> - display a menu with links to the other functionality of this servlet + * <li>op = gc - tell the JVM that we want to do a garbage collection and to run finalizers (@see + * java.lang.Runtime.getRuntime#gc() ) + * <li>op = general - display information about memory, and other JVM informatino + * <li>op = thread - display details about each thread. + * </UL> + * + * @see javax.servlet.http.HttpServlet#service(HttpServletRequest, HttpServletResponse) + */ + public void service(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + String op = request.getParameter("op"); + + response.setContentType("text/html"); + if (op == null) { + mainMenu(request, response); + } else if (op.equals("gc")) { + gc(request, response); + } else if (op.equals("general")) { + general(request, response); + } else if (op.equals("thread")) { + thread(request, response); + } + } + + private void mainMenu(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + response.getWriter().println("<HTML>"); + response.getWriter().println("<H1>"); + response.getWriter().println("<a href=" + request.getServletPath() + ">"); + response.getWriter().println("Main"); + response.getWriter().println("</a>"); + response.getWriter().println("</H1>"); + response.getWriter().println("<p>"); + response.getWriter().println("<table>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("<li>"); + response.getWriter().println("<a href=" + request.getServletPath() + "?op=general>"); + response.getWriter().println("General"); + response.getWriter().println("</a>"); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("<li>"); + response.getWriter().println("<a href=" + request.getServletPath() + "?op=gc>"); + response.getWriter().println("Garbage Collection"); + response.getWriter().println("</a>"); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("<li>"); + response.getWriter().println("<a href=" + request.getServletPath() + "?op=thread>"); + response.getWriter().println("Thread Listing"); + response.getWriter().println("</a>"); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("</table>"); + response.getWriter().println("</HTML>"); + } + + private void gc(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + java.lang.Runtime.getRuntime().gc(); + java.lang.Runtime.getRuntime().runFinalization(); + response.getWriter().println("<HTML>"); + response.getWriter().println("<H1>"); + response.getWriter().println("<a href=" + request.getServletPath() + ">"); + response.getWriter().println("Main"); + response.getWriter().println("</a>"); + response.getWriter().println(" : "); + response.getWriter().println("Garbage Collection"); + response.getWriter().println("</H1>"); + response.getWriter().println("<p>"); + response.getWriter().println("The garbage collector has been executed."); + response.getWriter().println("</HTML>"); + } + + private void general(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + response.getWriter().println("<HTML>"); + response.getWriter().println("<H1>"); + response.getWriter().println("<a href=" + request.getServletPath() + ">"); + response.getWriter().println("Main"); + response.getWriter().println("</a>"); + response.getWriter().println(" : "); + response.getWriter().println("General"); + response.getWriter().println("</H1>"); + response.getWriter().println("<p>"); + response.getWriter().println("<table>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Server Started Time:"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(new Date(CMS.getStartupTime())); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Current Time:"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(new Date()); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Available Processors:"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(Runtime.getRuntime().availableProcessors()); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Active Threads:"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(Thread.activeCount()); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Max Memory (in Bytes):"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(Runtime.getRuntime().maxMemory()); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Total Memory (in Bytes):"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(Runtime.getRuntime().totalMemory()); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Free Memory (in Bytes):"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(Runtime.getRuntime().freeMemory()); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("Free Memory / Total Memory:"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println( + (Runtime.getRuntime().freeMemory() * 100) / Runtime.getRuntime().totalMemory() + "%"); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + response.getWriter().println("</table>"); + response.getWriter().println("</HTML>"); + } + + private void thread(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + response.getWriter().println("</table>"); + response.getWriter().println("<HTML>"); + response.getWriter().println("<H1>"); + response.getWriter().println("<a href=" + request.getServletPath() + ">"); + response.getWriter().println("Main"); + response.getWriter().println("</a>"); + response.getWriter().println(" : "); + response.getWriter().println("Thread Listing"); + response.getWriter().println("</H1>"); + response.getWriter().println("<p>"); + response.getWriter().println("<table width=100% border=1>"); + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println("<b>"); + response.getWriter().println("#"); + response.getWriter().println("</b>"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println("<b>"); + response.getWriter().println("Name"); + response.getWriter().println("</b>"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println("<b>"); + response.getWriter().println("Priority"); + response.getWriter().println("</b>"); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println("<b>"); + response.getWriter().println("isDaemon"); + response.getWriter().println("</b>"); + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + int active = Thread.activeCount(); + Thread threads[] = new Thread[active]; + int c = Thread.enumerate(threads); + + for (int i = 0; i < c; i++) { + response.getWriter().println("<tr>"); + response.getWriter().println("<td>"); + response.getWriter().println(i); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(threads[i].getName()); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + response.getWriter().println(threads[i].getPriority()); + response.getWriter().println("</td>"); + response.getWriter().println("<td>"); + if (threads[i].isDaemon()) { + response.getWriter().println("true"); + } else { + response.getWriter().println("false"); + } + response.getWriter().println("</td>"); + response.getWriter().println("</tr>"); + } + response.getWriter().println("</table>"); + response.getWriter().println("</HTML>"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/UserInfo.java b/base/common/src/com/netscape/cms/servlet/base/UserInfo.java new file mode 100644 index 000000000..dd8f69613 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/UserInfo.java @@ -0,0 +1,90 @@ +// --- 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.base; + +/** + * This class represents information about the client e.g. version, + * langauge, vendor. + * + * @version $Revision$, $Date$ + */ +public class UserInfo { + public final static String MSIE = "MSIE"; + public final static String MOZILLA = "Mozilla"; + + /** + * Constructs a user information object. + */ + public UserInfo() { + } + + /** + * Returns the user language. + * + * @param s user language info from the browser + * @return user language + */ + public static String getUserLanguage(String s) { + // Does this contain a country code? + int pos = s.indexOf("-"); + + if (pos != -1) { + // Yes it does + return s.substring(0, pos); + } + return s; + } + + /** + * Returns the user country. + * + * @param s user language info from the browser + * @return user country + */ + public static String getUserCountry(String s) { + // Does this contain a country code? + int pos = s.indexOf("-"); + + if (pos != -1) { + // Yes it does + return s.substring(pos + 1); + } + return ""; + } + + /** + * Returns the users agent. + * + * @param s user language info from the browser + * @return user agent + */ + public static String getUserAgent(String s) { + // Check for MSIE + if (s.indexOf(MSIE) != -1) { + return MSIE; + } + + // Check for Netscape i.e. Mozilla + if (s.indexOf(MOZILLA) != -1) { + return MOZILLA; + } + + // Don't know agent. Return empty string. + return ""; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/base/model/Link.java b/base/common/src/com/netscape/cms/servlet/base/model/Link.java new file mode 100644 index 000000000..7fd850a22 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/base/model/Link.java @@ -0,0 +1,88 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK ---/** +package com.netscape.cms.servlet.base.model; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * @author alee + * + */ +@XmlRootElement(name = "Link") +public class Link { + protected String relationship; + protected String href; + protected String type; + + public Link() { + // required for jaxb + } + + public Link(String relationship, String href, String type) { + this.relationship = relationship; + this.href = href; + this.type = type; + } + + /** + * @return the relationship + */ + @XmlAttribute(name = "rel") + public String getRelationship() { + return relationship; + } + + /** + * @param relationship the relationship to set + */ + public void setRelationship(String relationship) { + this.relationship = relationship; + } + + /** + * @return the href + */ + @XmlAttribute + public String getHref() { + return href; + } + + /** + * @param href the href to set + */ + public void setHref(String href) { + this.href = href; + } + + /** + * @return the type + */ + @XmlAttribute + public String getType() { + return type; + } + + /** + * @param type the type to set + */ + public void setType(String type) { + this.type = type; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java b/base/common/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java new file mode 100644 index 000000000..5af09ad0d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java @@ -0,0 +1,1056 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.InvalidityDateExtension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.EMissingCredential; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertRecordList; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Utils; + +/** + * Revoke a certificate with a CMC-formatted revocation request + * + * @version $Revision$, $Date$ + */ +public class CMCRevReqServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 4731070386698127770L; + public final static String GETCERTS_FOR_CHALLENGE_REQUEST = "getCertsForChallenge"; + public static final String TOKEN_CERT_SERIAL = "certSerialToRevoke"; + // revocation templates. + private final static String TPL_FILE = "revocationResult.template"; + public static final String CRED_CMC = "cmcRequest"; + + private ICertificateRepository mCertDB = null; + private String mFormPath = null; + private IRequestQueue mQueue = null; + private IPublisherProcessor mPublisherProcessor = null; + private String mRequestID = null; + private final static String REVOKE = "revoke"; + private final static String ON_HOLD = "on-hold"; + private final static int ON_HOLD_REASON = 6; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7"; + + // http params + public static final String SERIAL_NO = TOKEN_CERT_SERIAL; + public static final String REASON_CODE = "reasonCode"; + public static final String CHALLENGE_PHRASE = "challengePhrase"; + + // request attributes + public static final String SERIALNO_ARRAY = "serialNoArray"; + + public CMCRevReqServlet() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + + super.init(sc); + + String authorityId = mAuthority.getId(); + + mFormPath = "/" + authorityId + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mAuthority instanceof ICertificateAuthority) { + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + } + + if (mAuthority instanceof ICertAuthority) { + mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor(); + } + mQueue = mAuthority.getRequestQueue(); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * + * <ul> + * <li>http.param cmcRequest the base-64 encoded CMC request + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + + String cmcAgentSerialNumber = null; + IArgBlock httpParams = cmsReq.getHttpParams(); + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + CMS.debug("**** mFormPath = " + mFormPath); + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + String cmc = (String) httpParams.get(CRED_CMC); + if (cmc == null) { + throw new EMissingCredential( + CMS.getUserMessage("CMS_AUTHENTICATION_NULL_CREDENTIAL", CRED_CMC)); + } + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, "revoke"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + //IAuthToken authToken = getAuthToken(cmsReq); + //Object subject = authToken.get(CMCAuth.TOKEN_CERT_SERIAL); + //Object uid = authToken.get("uid"); + //=========================== + String authMgr = AuditFormat.NOAUTH; + BigInteger[] serialNoArray = null; + + if (authToken != null) { + serialNoArray = authToken.getInBigIntegerArray(TOKEN_CERT_SERIAL); + } + + Integer reasonCode = Integer.valueOf(0); + if (authToken != null) { + reasonCode = authToken.getInInteger(REASON_CODE); + } + + String comments = ""; + Date invalidityDate = null; + String revokeAll = null; + int verifiedRecordCount = 0; + int totalRecordCount = 0; + + if (serialNoArray != null) { + totalRecordCount = serialNoArray.length; + verifiedRecordCount = serialNoArray.length; + } + + X509CertImpl[] certs = null; + + //for audit log. + String initiative = null; + + if (mAuthMgr != null && mAuthMgr.equals("CMCAuth")) { + // request is from agent + if (authToken != null) { + authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + String agentID = authToken.getInString("userid"); + + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID + + " authenticated by " + authMgr; + } + } else { + initiative = AuditFormat.FROMUSER; + } + + if ((serialNoArray != null) && (serialNoArray.length > 0)) { + if (mAuthority instanceof ICertificateAuthority) { + certs = new X509CertImpl[serialNoArray.length]; + + for (int i = 0; i < serialNoArray.length; i++) { + certs[i] = + ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificate( + serialNoArray[i]); + } + + } else if (mAuthority instanceof IRegistrationAuthority) { + IRequest getCertsChallengeReq = null; + + getCertsChallengeReq = mQueue.newRequest( + GETCERTS_FOR_CHALLENGE_REQUEST); + getCertsChallengeReq.setExtData(SERIALNO_ARRAY, serialNoArray); + mQueue.processRequest(getCertsChallengeReq); + RequestStatus status = getCertsChallengeReq.getRequestStatus(); + + if (status == RequestStatus.COMPLETE) { + certs = getCertsChallengeReq.getExtDataInCertArray(IRequest.OLD_CERTS); + header.addStringValue("request", getCertsChallengeReq.getRequestId().toString()); + mRequestID = getCertsChallengeReq.getRequestId().toString(); + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_GET_CERT_CHALL_PWRD")); + } + } + + header.addIntegerValue("totalRecordCount", serialNoArray.length); + header.addIntegerValue("verifiedRecordCount", serialNoArray.length); + + for (int i = 0; i < serialNoArray.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + serialNoArray[i], 16); + rarg.addStringValue("subject", + certs[i].getSubjectDN().toString()); + rarg.addLongValue("validNotBefore", + certs[i].getNotBefore().getTime() / 1000); + rarg.addLongValue("validNotAfter", + certs[i].getNotAfter().getTime() / 1000); + //argSet.addRepeatRecord(rarg); + } + + revokeAll = "(|(certRecordId=" + serialNoArray[0].toString() + "))"; + cmcAgentSerialNumber = authToken.getInString(IAuthManager.CRED_SSL_CLIENT_CERT); + process(argSet, header, reasonCode.intValue(), invalidityDate, initiative, req, resp, + verifiedRecordCount, revokeAll, totalRecordCount, + comments, locale[0], cmcAgentSerialNumber); + + } else { + header.addIntegerValue("totalRecordCount", 0); + header.addIntegerValue("verifiedRecordCount", 0); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if ((serialNoArray == null) || (serialNoArray.length == 0)) { + cmsReq.setStatus(CMSRequest.ERROR); + EBaseException ee = new EBaseException("No matched certificate is found"); + + cmsReq.setError(ee); + } else { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } + + /** + * Process cert status change request using the Certificate Management + * protocol using CMS (CMC) + * <P> + * + * (Certificate Request - an "EE" cert status change request) + * <P> + * + * (Certificate Request Processed - an "EE" cert status change request) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. - + * "revocation") is made (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is + * changed (revoked, expired, on-hold, off-hold) + * </ul> + * + * @param argSet CMS template parameters + * @param header argument block + * @param reason revocation reason (0 - Unspecified, 1 - Key compromised, + * 2 - CA key compromised; should not be used, 3 - Affiliation changed, + * 4 - Certificate superceded, 5 - Cessation of operation, or + * 6 - Certificate is on hold) + * @param invalidityDate certificate validity date + * @param initiative string containing the audit format + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param verifiedRecordCount number of verified records + * @param revokeAll string containing information on all of the + * certificates to be revoked + * @param totalRecordCount total number of records (verified and unverified) + * @param comments string containing certificate comments + * @param locale the system locale + * @exception EBaseException an error has occurred + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + int reason, Date invalidityDate, + String initiative, + HttpServletRequest req, + HttpServletResponse resp, + int verifiedRecordCount, + String revokeAll, + int totalRecordCount, + String comments, + Locale locale, String cmcAgentSerialNumber) + throws EBaseException { + String eeSerialNumber = null; + if (cmcAgentSerialNumber != null) { + eeSerialNumber = cmcAgentSerialNumber; + } else { + X509CertImpl sslCert = (X509CertImpl) getSSLClientCertificate(req); + if (sslCert != null) { + eeSerialNumber = sslCert.getSerialNumber().toString(); + } + } + + boolean auditRequest = true; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditSerialNumber = auditSerialNumber(eeSerialNumber); + String auditRequestType = auditRequestType(reason); + String auditApprovalStatus = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditReasonNum = String.valueOf(reason); + + try { + int count = 0; + Vector<X509CertImpl> oldCertsV = new Vector<X509CertImpl>(); + Vector<RevokedCertImpl> revCertImplsV = new Vector<RevokedCertImpl>(); + + // Construct a CRL reason code extension. + RevocationReason revReason = RevocationReason.fromInt(reason); + CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revReason); + + // Construct a CRL invalidity date extension. + InvalidityDateExtension invalidityDateExtn = null; + + if (invalidityDate != null) { + invalidityDateExtn = new InvalidityDateExtension(invalidityDate); + } + + // Construct a CRL extension for this request. + CRLExtensions entryExtn = new CRLExtensions(); + + if (crlReasonExtn != null) { + entryExtn.set(crlReasonExtn.getName(), crlReasonExtn); + } + if (invalidityDateExtn != null) { + entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn); + } + + if (mAuthority instanceof ICertificateAuthority) { + ICertRecordList list = (ICertRecordList) mCertDB.findCertRecordsInList( + revokeAll, null, totalRecordCount); + Enumeration<ICertRecord> e = list.getCertRecords(0, totalRecordCount - 1); + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = e.nextElement(); + X509CertImpl cert = rec.getCertificate(); + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert.getSerialNumber(), 16); + + if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + rarg.addStringValue("error", "Certificate " + + cert.getSerialNumber().toString() + + " is already revoked."); + } else { + oldCertsV.addElement(cert); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(cert.getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + } + argSet.addRepeatRecord(rarg); + } + + } else if (mAuthority instanceof IRegistrationAuthority) { + String reqIdStr = null; + + if (mRequestID != null && mRequestID.length() > 0) + reqIdStr = mRequestID; + Vector<String> serialNumbers = new Vector<String>(); + + if (revokeAll != null && revokeAll.length() > 0) { + for (int i = revokeAll.indexOf('='); i < revokeAll.length() && i > -1; i = + revokeAll.indexOf('=', i)) { + if (i > -1) { + i++; + while (i < revokeAll.length() && revokeAll.charAt(i) == ' ') { + i++; + } + String legalDigits = "0123456789"; + int j = i; + + while (j < revokeAll.length() && + legalDigits.indexOf(revokeAll.charAt(j)) != -1) { + j++; + } + if (j > i) { + serialNumbers.addElement(revokeAll.substring(i, j)); + } + } + } + } + if (reqIdStr != null && reqIdStr.length() > 0 && serialNumbers.size() > 0) { + IRequest certReq = mRequestQueue.findRequest(new RequestId(reqIdStr)); + X509CertImpl[] certs = certReq.getExtDataInCertArray(IRequest.OLD_CERTS); + + for (int i = 0; i < certs.length; i++) { + boolean addToList = false; + + for (int j = 0; j < serialNumbers.size(); j++) { + if (certs[i].getSerialNumber().toString().equals( + (String) serialNumbers.elementAt(j))) { + addToList = true; + break; + } + } + if (addToList) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + certs[i].getSerialNumber(), 16); + oldCertsV.addElement(certs[i]); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(certs[i].getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + argSet.addRepeatRecord(rarg); + } + } + } else { + String b64eCert = req.getParameter("b64eCertificate"); + + if (b64eCert != null) { + byte[] certBytes = Utils.base64decode(b64eCert); + X509CertImpl cert = new X509CertImpl(certBytes); + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert.getSerialNumber(), 16); + oldCertsV.addElement(cert); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(cert.getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + argSet.addRepeatRecord(rarg); + } + } + } + + header.addIntegerValue("totalRecordCount", count); + + X509CertImpl[] oldCerts = new X509CertImpl[count]; + RevokedCertImpl[] revCertImpls = new RevokedCertImpl[count]; + + for (int i = 0; i < count; i++) { + oldCerts[i] = (X509CertImpl) oldCertsV.elementAt(i); + revCertImpls[i] = (RevokedCertImpl) revCertImplsV.elementAt(i); + } + + IRequest revReq = + mQueue.newRequest(IRequest.REVOCATION_REQUEST); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + revReq.setExtData(IRequest.CERT_INFO, revCertImpls); + revReq.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST); + revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT); + revReq.setExtData(IRequest.REVOKED_REASON, reason); + revReq.setExtData(IRequest.OLD_CERTS, oldCerts); + if (comments != null) { + revReq.setExtData(IRequest.REQUESTOR_COMMENTS, comments); + } + + // change audit processing from "REQUEST" to "REQUEST_PROCESSED" + // to distinguish which type of signed audit log message to save + // as a failure outcome in case an exception occurs + auditRequest = false; + + mQueue.processRequest(revReq); + + // retrieve the request status + auditApprovalStatus = revReq.getRequestStatus().toString(); + + RequestStatus stat = revReq.getRequestStatus(); + + if (stat == RequestStatus.COMPLETE) { + // audit log the error + Integer result = revReq.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + String[] svcErrors = + revReq.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + //cmsReq.setErrorDescription(err); + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed with error: " + + err, + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + } + return; + } + + // audit log the success. + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed", + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + + header.addStringValue("revoked", "yes"); + + Integer updateCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS); + + if (updateCRLResult != null) { + header.addStringValue("updateCRL", "yes"); + if (updateCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("updateCRLSuccess", "yes"); + } else { + header.addStringValue("updateCRLSuccess", "no"); + String crlError = + revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR); + + if (crlError != null) + header.addStringValue("updateCRLError", + crlError); + } + // let known crl publishing status too. + Integer publishCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS); + + if (publishCRLResult != null) { + if (publishCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("publishCRLSuccess", "yes"); + } else { + header.addStringValue("publishCRLSuccess", "no"); + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) + header.addStringValue("publishCRLError", + publError); + } + } + } + if (mAuthority instanceof ICertificateAuthority) { + // let known update and publish status of all crls. + Enumeration<ICRLIssuingPoint> otherCRLs = + ((ICertificateAuthority) mAuthority).getCRLIssuingPoints(); + + while (otherCRLs.hasMoreElements()) { + ICRLIssuingPoint crl = (ICRLIssuingPoint) + otherCRLs.nextElement(); + String crlId = crl.getId(); + + if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL)) + continue; + String updateStatusStr = crl.getCrlUpdateStatusStr(); + Integer updateResult = revReq.getExtDataInInteger(updateStatusStr); + + if (updateResult != null) { + if (updateResult.equals(IRequest.RES_SUCCESS)) { + CMS.debug("CMCRevReqServlet: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER", + updateStatusStr)); + header.addStringValue(updateStatusStr, "yes"); + } else { + String updateErrorStr = crl.getCrlUpdateErrorStr(); + + CMS.debug("CMCRevReqServlet: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO", + updateStatusStr)); + header.addStringValue(updateStatusStr, "no"); + String error = + revReq.getExtDataInString(updateErrorStr); + + if (error != null) + header.addStringValue(updateErrorStr, + error); + } + String publishStatusStr = crl.getCrlPublishStatusStr(); + Integer publishResult = + revReq.getExtDataInInteger(publishStatusStr); + + if (publishResult == null) + continue; + if (publishResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue(publishStatusStr, "yes"); + } else { + String publishErrorStr = + crl.getCrlPublishErrorStr(); + + header.addStringValue(publishStatusStr, "no"); + String error = + revReq.getExtDataInString(publishErrorStr); + + if (error != null) + header.addStringValue( + publishErrorStr, error); + } + } + } + } + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + header.addStringValue("dirEnabled", "yes"); + Integer[] ldapPublishStatus = + revReq.getExtDataInIntegerArray("ldapPublishStatus"); + int certsToUpdate = 0; + int certsUpdated = 0; + + if (ldapPublishStatus != null) { + certsToUpdate = ldapPublishStatus.length; + for (int i = 0; i < certsToUpdate; i++) { + if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) { + certsUpdated++; + } + } + } + header.addIntegerValue("certsUpdated", certsUpdated); + header.addIntegerValue("certsToUpdate", certsToUpdate); + + // add crl publishing status. + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) { + header.addStringValue("crlPublishError", + publError); + } + } else { + header.addStringValue("dirEnabled", "no"); + } + header.addStringValue("error", null); + + } else if (stat == RequestStatus.PENDING) { + header.addStringValue("error", "Request Pending"); + header.addStringValue("revoked", "pending"); + // audit log the pending + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "pending", + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + + } else { + Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS); + StringBuffer errorStr = new StringBuffer(); + + if (errors != null && errors.size() > 0) { + for (int ii = 0; ii < errors.size(); ii++) { + errorStr.append(errors.elementAt(ii)); + ; + } + } + header.addStringValue("error", errorStr.toString()); + header.addStringValue("revoked", "no"); + // audit log the error + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + stat.toString(), + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + + // store a message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + + } catch (CertificateException e) { + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + log(ILogger.LL_FAILURE, "error " + e); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, "error " + e); + + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + throw e; + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED", e.toString())); + + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED")); + } catch (Exception e) { + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + e.printStackTrace(); + } + + return; + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @param req HTTP request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = null; + + // Obtain the requesterID + requesterID = req.getParameter("requestId"); + + if (requesterID != null) { + requesterID = requesterID.trim(); + } else { + requesterID = ILogger.UNIDENTIFIED; + } + + return requesterID; + } + + /** + * Signed Audit Log Serial Number + * + * This method is called to obtain the serial number of the certificate + * whose status is to be changed for a signed audit log message. + * <P> + * + * @param eeSerialNumber a string containing the un-normalized serialNumber + * @return id string containing the signed audit log message RequesterID + */ + private String auditSerialNumber(String eeSerialNumber) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String serialNumber = null; + + // Normalize the serialNumber + if (eeSerialNumber != null) { + serialNumber = eeSerialNumber.trim(); + + // convert it to hexadecimal + serialNumber = "0x" + + Integer.toHexString( + Integer.valueOf(serialNumber).intValue()); + } else { + serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + return serialNumber; + } + + /** + * Signed Audit Log Request Type + * + * This method is called to obtain the "Request Type" for + * a signed audit log message. + * <P> + * + * @param reason an integer denoting the revocation reason + * @return string containing REVOKE or ON_HOLD + */ + private String auditRequestType(int reason) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requestType = null; + + // Determine the revocation type based upon the revocation reason + if (reason == ON_HOLD_REASON) { + requestType = ON_HOLD; + } else { + requestType = REVOKE; + } + + return requestType; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java b/base/common/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java new file mode 100644 index 000000000..f056047cc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java @@ -0,0 +1,716 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.InvalidityDateExtension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertRecordList; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Utils; + +/** + * Takes the certificate info (serial number) and optional challenge phrase, creates a + * revocation request and submits it to the authority subsystem for processing + * + * @version $Revision$, $Date$ + */ +public class ChallengeRevocationServlet1 extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 1253319999546210407L; + public final static String GETCERTS_FOR_CHALLENGE_REQUEST = "getCertsForChallenge"; + public static final String TOKEN_CERT_SERIAL = "certSerialToRevoke"; + // revocation templates. + private final static String TPL_FILE = "revocationResult.template"; + + private ICertificateRepository mCertDB = null; + private String mFormPath = null; + private IRequestQueue mQueue = null; + private IPublisherProcessor mPublisherProcessor = null; + private String mRequestID = null; + + // http params + public static final String SERIAL_NO = TOKEN_CERT_SERIAL; + public static final String REASON_CODE = "reasonCode"; + public static final String CHALLENGE_PHRASE = "challengePhrase"; + + // request attributes + public static final String SERIALNO_ARRAY = "serialNoArray"; + + public ChallengeRevocationServlet1() { + super(); + } + + /** + * Initialize the servlet. This servlet uses the file + * revocationResult.template for the response + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + String authorityId = mAuthority.getId(); + + mFormPath = "/" + authorityId + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mAuthority instanceof ICertificateAuthority) { + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + } + + if (mAuthority instanceof ICertAuthority) { + mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor(); + } + mQueue = mAuthority.getRequestQueue(); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param REASON_CODE the revocation reason + * <li>http.param b64eCertificate the base-64 encoded certificate to revoke + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + IArgBlock httpParams = cmsReq.getHttpParams(); + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + // for audit log + IAuthToken authToken = authenticate(cmsReq); + String authMgr = AuditFormat.NOAUTH; + + BigInteger[] serialNoArray = null; + + if (authToken != null) { + serialNoArray = authToken.getInBigIntegerArray(SERIAL_NO); + } + // set revocation reason, default to unspecified if not set. + int reasonCode = + httpParams.getValueAsInt(REASON_CODE, 0); + // header.addIntegerValue("reason", reasonCode); + + String comments = req.getParameter(IRequest.REQUESTOR_COMMENTS); + Date invalidityDate = null; + String revokeAll = null; + int totalRecordCount = (serialNoArray != null) ? serialNoArray.length : 0; + int verifiedRecordCount = (serialNoArray != null) ? serialNoArray.length : 0; + + X509CertImpl[] certs = null; + + //for audit log. + String initiative = null; + + if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + // request is from agent + if (authToken != null) { + authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + String agentID = authToken.getInString("userid"); + + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID + + " authenticated by " + authMgr; + } + } else { + initiative = AuditFormat.FROMUSER; + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "revoke"); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + if (serialNoArray != null && serialNoArray.length > 0) { + if (mAuthority instanceof ICertificateAuthority) { + certs = new X509CertImpl[serialNoArray.length]; + + for (int i = 0; i < serialNoArray.length; i++) { + certs[i] = + ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificate( + serialNoArray[i]); + } + + } else if (mAuthority instanceof IRegistrationAuthority) { + IRequest getCertsChallengeReq = null; + + getCertsChallengeReq = mQueue.newRequest( + GETCERTS_FOR_CHALLENGE_REQUEST); + getCertsChallengeReq.setExtData(SERIALNO_ARRAY, serialNoArray); + mQueue.processRequest(getCertsChallengeReq); + RequestStatus status = getCertsChallengeReq.getRequestStatus(); + + if (status == RequestStatus.COMPLETE) { + certs = getCertsChallengeReq.getExtDataInCertArray(IRequest.OLD_CERTS); + header.addStringValue("request", getCertsChallengeReq.getRequestId().toString()); + mRequestID = getCertsChallengeReq.getRequestId().toString(); + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_FAIL_GET_CERT_CHALL_PWRD")); + } + } + + header.addIntegerValue("totalRecordCount", serialNoArray.length); + header.addIntegerValue("verifiedRecordCount", serialNoArray.length); + + for (int i = 0; i < serialNoArray.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + serialNoArray[i], 16); + rarg.addStringValue("subject", + certs[i].getSubjectDN().toString()); + rarg.addLongValue("validNotBefore", + certs[i].getNotBefore().getTime() / 1000); + rarg.addLongValue("validNotAfter", + certs[i].getNotAfter().getTime() / 1000); + //argSet.addRepeatRecord(rarg); + } + + revokeAll = "(|(certRecordId=" + serialNoArray[0].toString() + "))"; + process(argSet, header, reasonCode, invalidityDate, initiative, req, resp, + verifiedRecordCount, revokeAll, totalRecordCount, + comments, locale[0]); + } else { + header.addIntegerValue("totalRecordCount", 0); + header.addIntegerValue("verifiedRecordCount", 0); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (serialNoArray == null) { + CMS.debug("ChallengeRevcationServlet1::process() - " + + " serialNoArray is null!"); + EBaseException ee = new EBaseException("No matched certificate is found"); + + cmsReq.setError(ee); + return; + } + + if (serialNoArray.length == 0) { + cmsReq.setStatus(CMSRequest.ERROR); + EBaseException ee = new EBaseException("No matched certificate is found"); + + cmsReq.setError(ee); + } else { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } + + private void process(CMSTemplateParams argSet, IArgBlock header, + int reason, Date invalidityDate, + String initiative, + HttpServletRequest req, + HttpServletResponse resp, + int verifiedRecordCount, + String revokeAll, + int totalRecordCount, + String comments, + Locale locale) + throws EBaseException { + try { + int count = 0; + Vector<X509CertImpl> oldCertsV = new Vector<X509CertImpl>(); + Vector<RevokedCertImpl> revCertImplsV = new Vector<RevokedCertImpl>(); + + // Construct a CRL reason code extension. + RevocationReason revReason = RevocationReason.fromInt(reason); + CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revReason); + + // Construct a CRL invalidity date extension. + InvalidityDateExtension invalidityDateExtn = null; + + if (invalidityDate != null) { + invalidityDateExtn = new InvalidityDateExtension(invalidityDate); + } + + // Construct a CRL extension for this request. + CRLExtensions entryExtn = new CRLExtensions(); + + if (crlReasonExtn != null) { + entryExtn.set(crlReasonExtn.getName(), crlReasonExtn); + } + if (invalidityDateExtn != null) { + entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn); + } + + if (mAuthority instanceof ICertificateAuthority) { + ICertRecordList list = (ICertRecordList) mCertDB.findCertRecordsInList( + revokeAll, null, totalRecordCount); + Enumeration<ICertRecord> e = list.getCertRecords(0, totalRecordCount - 1); + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = e.nextElement(); + X509CertImpl cert = rec.getCertificate(); + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert.getSerialNumber(), 16); + + if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + rarg.addStringValue("error", "Certificate " + + cert.getSerialNumber().toString() + + " is already revoked."); + } else { + oldCertsV.addElement(cert); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(cert.getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + } + argSet.addRepeatRecord(rarg); + } + + } else if (mAuthority instanceof IRegistrationAuthority) { + String reqIdStr = null; + + if (mRequestID != null && mRequestID.length() > 0) + reqIdStr = mRequestID; + Vector<String> serialNumbers = new Vector<String>(); + + if (revokeAll != null && revokeAll.length() > 0) { + for (int i = revokeAll.indexOf('='); i < revokeAll.length() && i > -1; + i = revokeAll.indexOf('=', i)) { + if (i > -1) { + i++; + while (i < revokeAll.length() && revokeAll.charAt(i) == ' ') { + i++; + } + String legalDigits = "0123456789"; + int j = i; + + while (j < revokeAll.length() && + legalDigits.indexOf(revokeAll.charAt(j)) != -1) { + j++; + } + if (j > i) { + serialNumbers.addElement(revokeAll.substring(i, j)); + } + } + } + } + if (reqIdStr != null && reqIdStr.length() > 0 && serialNumbers.size() > 0) { + IRequest certReq = mRequestQueue.findRequest(new RequestId(reqIdStr)); + X509CertImpl[] certs = certReq.getExtDataInCertArray(IRequest.OLD_CERTS); + + for (int i = 0; i < certs.length; i++) { + boolean addToList = false; + + for (int j = 0; j < serialNumbers.size(); j++) { + if (certs[i].getSerialNumber().toString().equals( + (String) serialNumbers.elementAt(j))) { + addToList = true; + break; + } + } + if (addToList) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + certs[i].getSerialNumber(), 16); + oldCertsV.addElement(certs[i]); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(certs[i].getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + argSet.addRepeatRecord(rarg); + } + } + } else { + String b64eCert = req.getParameter("b64eCertificate"); + + if (b64eCert != null) { + byte[] certBytes = Utils.base64decode(b64eCert); + X509CertImpl cert = new X509CertImpl(certBytes); + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert.getSerialNumber(), 16); + oldCertsV.addElement(cert); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(cert.getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + argSet.addRepeatRecord(rarg); + } + } + } + + header.addIntegerValue("totalRecordCount", count); + + X509CertImpl[] oldCerts = new X509CertImpl[count]; + RevokedCertImpl[] revCertImpls = new RevokedCertImpl[count]; + + for (int i = 0; i < count; i++) { + oldCerts[i] = (X509CertImpl) oldCertsV.elementAt(i); + revCertImpls[i] = (RevokedCertImpl) revCertImplsV.elementAt(i); + } + + IRequest revReq = + mQueue.newRequest(IRequest.REVOCATION_REQUEST); + + revReq.setExtData(IRequest.CERT_INFO, revCertImpls); + revReq.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST); + revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT); + + revReq.setExtData(IRequest.OLD_CERTS, oldCerts); + if (comments != null) { + revReq.setExtData(IRequest.REQUESTOR_COMMENTS, comments); + } + + mQueue.processRequest(revReq); + RequestStatus stat = revReq.getRequestStatus(); + + if (stat == RequestStatus.COMPLETE) { + // audit log the error + Integer result = revReq.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + String[] svcErrors = + revReq.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + //cmsReq.setErrorDescription(err); + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed with error: " + + err, + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + } + return; + } + + // audit log the success. + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed", + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + + header.addStringValue("revoked", "yes"); + + Integer updateCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS); + + if (updateCRLResult != null) { + header.addStringValue("updateCRL", "yes"); + if (updateCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("updateCRLSuccess", "yes"); + } else { + header.addStringValue("updateCRLSuccess", "no"); + String crlError = + revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR); + + if (crlError != null) + header.addStringValue("updateCRLError", + crlError); + } + // let known crl publishing status too. + Integer publishCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS); + + if (publishCRLResult != null) { + if (publishCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("publishCRLSuccess", "yes"); + } else { + header.addStringValue("publishCRLSuccess", "no"); + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) + header.addStringValue("publishCRLError", + publError); + } + } + } + if (mAuthority instanceof ICertificateAuthority) { + // let known update and publish status of all crls. + Enumeration<ICRLIssuingPoint> otherCRLs = + ((ICertificateAuthority) mAuthority).getCRLIssuingPoints(); + + while (otherCRLs.hasMoreElements()) { + ICRLIssuingPoint crl = (ICRLIssuingPoint) + otherCRLs.nextElement(); + String crlId = crl.getId(); + + if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL)) + continue; + String updateStatusStr = crl.getCrlUpdateStatusStr(); + Integer updateResult = revReq.getExtDataInInteger(updateStatusStr); + + if (updateResult != null) { + if (updateResult.equals(IRequest.RES_SUCCESS)) { + CMS.debug("ChallengeRevcationServlet1: " + + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER", + updateStatusStr)); + header.addStringValue(updateStatusStr, "yes"); + } else { + String updateErrorStr = crl.getCrlUpdateErrorStr(); + + CMS.debug("ChallengeRevcationServlet1: " + + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO", + updateStatusStr)); + header.addStringValue(updateStatusStr, "no"); + String error = + revReq.getExtDataInString(updateErrorStr); + + if (error != null) + header.addStringValue(updateErrorStr, + error); + } + String publishStatusStr = crl.getCrlPublishStatusStr(); + Integer publishResult = + revReq.getExtDataInInteger(publishStatusStr); + + if (publishResult == null) + continue; + if (publishResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue(publishStatusStr, "yes"); + } else { + String publishErrorStr = + crl.getCrlPublishErrorStr(); + + header.addStringValue(publishStatusStr, "no"); + String error = + revReq.getExtDataInString(publishErrorStr); + + if (error != null) + header.addStringValue( + publishErrorStr, error); + } + } + } + } + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + header.addStringValue("dirEnabled", "yes"); + Integer[] ldapPublishStatus = + revReq.getExtDataInIntegerArray("ldapPublishStatus"); + int certsToUpdate = 0; + int certsUpdated = 0; + + if (ldapPublishStatus != null) { + certsToUpdate = ldapPublishStatus.length; + for (int i = 0; i < certsToUpdate; i++) { + if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) { + certsUpdated++; + } + } + } + header.addIntegerValue("certsUpdated", certsUpdated); + header.addIntegerValue("certsToUpdate", certsToUpdate); + + // add crl publishing status. + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) { + header.addStringValue("crlPublishError", + publError); + } + } else { + header.addStringValue("dirEnabled", "no"); + } + header.addStringValue("error", null); + + } else if (stat == RequestStatus.PENDING) { + header.addStringValue("error", "Request Pending"); + header.addStringValue("revoked", "pending"); + // audit log the pending + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "pending", + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + + } else { + Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS); + StringBuffer errorStr = new StringBuffer(); + + if (errors != null && errors.size() > 0) { + for (int ii = 0; ii < errors.size(); ii++) { + errorStr.append(errors.elementAt(ii)); + } + } + header.addStringValue("error", errorStr.toString()); + header.addStringValue("revoked", "no"); + // audit log the error + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + stat.toString(), + oldCerts[j].getSubjectDN(), + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, "error " + e); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, "error " + e); + throw e; + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED")); + } catch (Exception e) { + e.printStackTrace(); + } + + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/CloneRedirect.java b/base/common/src/com/netscape/cms/servlet/cert/CloneRedirect.java new file mode 100644 index 000000000..d17fd959b --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/CloneRedirect.java @@ -0,0 +1,142 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Redirect a request to the Master. This servlet is used in + * a clone when a requested service (such as CRL) is not available. + * It redirects the user to the master. + * + * @version $Revision$, $Date$ + */ +public class CloneRedirect extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 3217967115281965166L; + private final static String PROP_REDIRECT_URL = "masterURL"; + private final static String TPL_FILE = "cloneRedirect.template"; + + private String mNewUrl = null; + private String mFormPath = null; + + private ICertificateAuthority mCA = null; + + /** + * Constructs CloneRedirect servlet. + */ + public CloneRedirect() { + super(); + + } + + /** + * Initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + if (mAuthority instanceof ICertificateAuthority) { + mCA = (ICertificateAuthority) mAuthority; + IConfigStore authConfig = mCA.getConfigStore(); + + if (authConfig != null) { + try { + mNewUrl = authConfig.getString(PROP_REDIRECT_URL, + "*** master URL unavailable, check your configuration ***"); + } catch (EBaseException e) { + // do nothing + } + } + } + + if (mAuthority instanceof ICertificateAuthority) + mCA = (ICertificateAuthority) mAuthority; + + // override success to do output with our own template. + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Serves HTTP request. + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + CMS.debug("CloneRedirect: " + CMS.getLogMessage("ADMIN_SRVLT_ADD_MASTER_URL", mNewUrl)); + header.addStringValue("masterURL", mNewUrl); + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DirAuthServlet.java b/base/common/src/com/netscape/cms/servlet/cert/DirAuthServlet.java new file mode 100644 index 000000000..ced92ba85 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DirAuthServlet.java @@ -0,0 +1,241 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Date; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.cms.authentication.HashAuthentication; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * 'Face-to-face' certificate enrollment. + * + * @version $Revision$, $Date$ + */ +public class DirAuthServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 3906057586972768401L; + private final static String TPL_FILE = "/ra/hashEnrollmentSubmit.template"; + private final static String TPL_ERROR_FILE = "/ra/GenErrorHashDirEnroll.template"; + private String mFormPath = null; + + public DirAuthServlet() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + try { + mFormPath = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE); + if (mFormPath == null) + mFormPath = TPL_FILE; + } catch (Exception e) { + } + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Process the HTTP request. This servlet reads configuration information + * from the hashDirEnrollment configuration substore + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + String reqHost = httpReq.getRemoteHost(); + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + if (!(mAuthority instanceof IRegistrationAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_CA_FROM_RA_NOT_IMP")); + cmsReq.setError(new ECMSGWException( + CMS.getLogMessage("CMSGW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + cmsReq.setError(new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "submit"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + IConfigStore configStore = CMS.getConfigStore(); + String val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr; + + Date date = new Date(); + long currTime = date.getTime(); + long timeout = mgr.getTimeout(reqHost); + long lastlogin = mgr.getLastLogin(reqHost); + long diff = currTime - lastlogin; + + boolean enable = mgr.isEnable(reqHost); + + if (!enable) { + printError(cmsReq, "0"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + if (lastlogin == 0) + mgr.setLastLogin(reqHost, currTime); + else if (diff > timeout) { + mgr.disable(reqHost); + printError(cmsReq, "2"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + mgr.setLastLogin(reqHost, currTime); + + String uid = args.getValueAsString("uid"); + long pageid = mgr.getPageID(); + String pageID = pageid + ""; + + mgr.addAuthToken(pageID, authToken); + + header.addStringValue("pageID", pageID); + header.addStringValue("uid", uid); + header.addStringValue("fingerprint", mgr.hashFingerprint(reqHost, pageID, uid)); + header.addStringValue("hostname", reqHost); + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + private void printError(CMSRequest cmsReq, String errorCode) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + mTemplates.remove(CMSRequest.SUCCESS); + header.addStringValue("authority", "Registration Manager"); + header.addStringValue("errorCode", errorCode); + String formPath = TPL_ERROR_FILE; + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(formPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", formPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java b/base/common/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java new file mode 100644 index 000000000..a5cdc98e8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java @@ -0,0 +1,173 @@ +// --- 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.cert; + +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.cms.authentication.HashAuthentication; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * For Face-to-face enrollment, disable EE enrollment feature + * + * @version $Revision$, $Date$ + * @see com.netscape.cms.servlet.cert.EnableEnrollResult + */ +public class DisableEnrollResult extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 4307655310299723974L; + private final static String TPL_FILE = "enableEnrollResult.template"; + private String mFormPath = null; + + public DisableEnrollResult() { + super(); + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // coming from agent + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + protected CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Services the request + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken token = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, token, + mAuthzResourceName, "disable"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + X509Certificate sslClientCert = null; + + sslClientCert = getSSLClientCertificate(httpReq); + String dn = (String) sslClientCert.getSubjectDN().toString(); + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + if (!(mAuthority instanceof IRegistrationAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_CA_FROM_RA_NOT_IMP")); + cmsReq.setError(new ECMSGWException( + CMS.getLogMessage("CMSGW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IConfigStore configStore = CMS.getConfigStore(); + String val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr; + + String host = args.getValueAsString("hosts", null); + String name = mgr.getAgentName(host); + + if (name == null) { + header.addStringValue("code", "2"); + } else if (name.equals(dn)) { + mgr.disable(host); + header.addStringValue("code", "2"); + } else { + header.addStringValue("code", "3"); + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DisplayBySerial.java b/base/common/src/com/netscape/cms/servlet/cert/DisplayBySerial.java new file mode 100644 index 000000000..5a1e4ed65 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DisplayBySerial.java @@ -0,0 +1,488 @@ +// --- 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.cert; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.pkcs.ContentInfo; +import netscape.security.pkcs.PKCS7; +import netscape.security.pkcs.SignerInfo; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.Extension; +import netscape.security.x509.KeyUsageExtension; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.ICertPrettyPrint; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.EDBRecordNotFoundException; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.dbs.certdb.IRevocationInfo; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Utils; + +/** + * Display detailed information about a certificate + * + * The template 'displayBySerial.template' is used to + * render the response for this servlet. + * + * @version $Revision$, $Date$ + */ +public class DisplayBySerial extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -4143700762995036597L; + private final static String INFO = "DisplayBySerial"; + private final static String TPL_FILE1 = "displayBySerial.template"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + + private ICertificateRepository mCertDB = null; + private String mForm1Path = null; + private X509Certificate mCACerts[] = null; + + /** + * Constructs DisplayBySerial servlet. + */ + public DisplayBySerial() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + if (mAuthority instanceof ICertificateAuthority) { + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + } + try { + mCACerts = ((ICertAuthority) mAuthority).getCACertChain().getChain(); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CA_CHAIN_NOT_AVAILABLE")); + } + // coming from ee + mForm1Path = "/" + mAuthority.getId() + "/" + TPL_FILE1; + + if (mOutputTemplatePath != null) + mForm1Path = mOutputTemplatePath; + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Serves HTTP request. The format of this request is as follows: + * <ul> + * <li>http.param serialNumber Decimal serial number of certificate to display (or hex if serialNumber preceded by + * 0x) + * </ul> + */ + public void process(CMSRequest cmsReq) throws EBaseException { + BigInteger serialNumber = MINUS_ONE; + EBaseException error = null; + String certType[] = new String[1]; + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + serialNumber = getSerialNumber(req); + getCertRecord(serialNumber, certType); //throw exception on error + + if (certType[0].equalsIgnoreCase("x509")) { + form = getTemplate(mForm1Path, req, locale); + } + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", String.valueOf(serialNumber))); + + error = new ECMSGWException(CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mForm1Path, e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } catch (EDBRecordNotFoundException e) { + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_CERT_SERIAL_NOT_FOUND_1", "0x" + serialNumber.toString(16))); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + try { + if (serialNumber.compareTo(MINUS_ONE) > 0) { + process(argSet, header, serialNumber, + req, resp, locale[0]); + } else { + error = new ECMSGWException( + CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUMBER")); + } + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + } + + /** + * Display information about a particular certificate + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + BigInteger seq, HttpServletRequest req, + HttpServletResponse resp, + Locale locale) + throws EBaseException { + String certType[] = new String[1]; + + try { + getCertRecord(seq, certType); // throw exception on error + + if (certType[0].equalsIgnoreCase("x509")) { + processX509(argSet, header, seq, req, resp, locale); + return; + } + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_DISP_BY_SERIAL", e.toString())); + throw e; + } + + return; + } + + private void processX509(CMSTemplateParams argSet, IArgBlock header, + BigInteger seq, HttpServletRequest req, + HttpServletResponse resp, + Locale locale) + throws EBaseException { + try { + ICertRecord rec = (ICertRecord) mCertDB.readCertificateRecord(seq); + if (rec == null) { + CMS.debug("DisplayBySerial: failed to read record"); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT")); + } + X509CertImpl cert = rec.getCertificate(); + if (cert == null) { + CMS.debug("DisplayBySerial: no certificate in record"); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT")); + } + + try { + X509CertInfo info = (X509CertInfo) cert.get(X509CertImpl.NAME + "." + X509CertImpl.INFO); + if (info == null) { + CMS.debug("DisplayBySerial: no info found"); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT")); + } + CertificateExtensions extensions = (CertificateExtensions) info.get(X509CertInfo.EXTENSIONS); + + boolean emailCert = false; + + if (extensions != null) { + for (int i = 0; i < extensions.size(); i++) { + Extension ext = (Extension) extensions.elementAt(i); + + if (ext instanceof NSCertTypeExtension) { + NSCertTypeExtension type = (NSCertTypeExtension) ext; + + if (((Boolean) type.get(NSCertTypeExtension.EMAIL)).booleanValue()) + emailCert = true; + } + if (ext instanceof KeyUsageExtension) { + KeyUsageExtension usage = + (KeyUsageExtension) ext; + + try { + if (((Boolean) usage.get(KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue() || + ((Boolean) usage.get(KeyUsageExtension.DATA_ENCIPHERMENT)).booleanValue()) + emailCert = true; + } catch (ArrayIndexOutOfBoundsException e) { + // bug356108: + // In case there is only DIGITAL_SIGNATURE, + // don't report error + } + } + } + } + header.addBooleanValue("emailCert", emailCert); + + boolean noCertImport = true; + MetaInfo metaInfo = (MetaInfo) rec.get(ICertRecord.ATTR_META_INFO); + + if (metaInfo != null) { + String rid = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + + if (rid != null && mAuthority instanceof ICertificateAuthority) { + IRequest r = + ((ICertificateAuthority) mAuthority).getRequestQueue().findRequest(new RequestId(rid)); + String certType = r.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE); + + if (certType != null && certType.equals(IRequest.CLIENT_CERT)) { + noCertImport = false; + } + } + } + header.addBooleanValue("noCertImport", noCertImport); + + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_PARSING_EXTENS", e.toString())); + } + + IRevocationInfo revocationInfo = rec.getRevocationInfo(); + + if (revocationInfo != null) { + CRLExtensions crlExts = revocationInfo.getCRLEntryExtensions(); + + if (crlExts != null) { + Enumeration<Extension> enumx = crlExts.getElements(); + int reason = 0; + + while (enumx.hasMoreElements()) { + Extension ext = (Extension) enumx.nextElement(); + + if (ext instanceof CRLReasonExtension) { + reason = ((CRLReasonExtension) ext).getReason().toInt(); + } + } + header.addIntegerValue("revocationReason", reason); + } + } + + ICertPrettyPrint certDetails = CMS.getCertPrettyPrint(cert); + + header.addStringValue("certPrettyPrint", + certDetails.toString(locale)); + + /* + String scheme = req.getScheme(); + if (scheme.equals("http") && connectionIsSSL(req)) + scheme = "https"; + String requestURI = req.getRequestURI(); + int i = requestURI.indexOf('?'); + String newRequestURI = + (i > -1)? requestURI.substring(0, i): requestURI; + header.addStringValue("serviceURL", scheme +"://"+ + req.getServerName() + ":"+ + req.getServerPort() + newRequestURI); + */ + header.addStringValue("authorityid", mAuthority.getId()); + + String certFingerprints = ""; + + try { + certFingerprints = CMS.getFingerPrints(cert); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_DIGESTING_CERT", e.toString())); + } + if (certFingerprints.length() > 0) + header.addStringValue("certFingerprint", certFingerprints); + + byte[] ba = cert.getEncoded(); + // Do base 64 encoding + + header.addStringValue("certChainBase64", Utils.base64encode(ba)); + header.addStringValue("serialNumber", seq.toString(16)); + + /* + String userAgent = req.getHeader("user-agent"); + String agent = + (userAgent != null)? UserInfo.getUserAgent(userAgent): ""; + */ + // Now formulate a PKCS#7 blob + X509CertImpl[] certsInChain = new X509CertImpl[1]; + ; + if (mCACerts != null) { + for (int i = 0; i < mCACerts.length; i++) { + if (cert.equals(mCACerts[i])) { + certsInChain = new + X509CertImpl[mCACerts.length]; + break; + } + certsInChain = new X509CertImpl[mCACerts.length + 1]; + } + } + + // Set the EE cert + certsInChain[0] = cert; + + // Set the Ca certificate chain + if (mCACerts != null) { + for (int i = 0; i < mCACerts.length; i++) { + if (!cert.equals(mCACerts[i])) + certsInChain[i + 1] = (X509CertImpl) mCACerts[i]; + } + } + + // Wrap the chain into a degenerate P7 object + String p7Str; + + try { + PKCS7 p7 = new PKCS7(new AlgorithmId[0], + new ContentInfo(new byte[0]), + certsInChain, + new SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + p7.encodeSignedData(bos, false); + byte[] p7Bytes = bos.toByteArray(); + + p7Str = Utils.base64encode(p7Bytes); + header.addStringValue("pkcs7ChainBase64", p7Str); + } catch (Exception e) { + //p7Str = "PKCS#7 B64 Encoding error - " + e.toString() + //+ "; Please contact your administrator"; + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_FORMING_PKCS7_1", e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_FORMING_PKCS7")); + } + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("MSGW_ERR_DISP_BY_SERIAL", e.toString())); + throw e; + } catch (CertificateEncodingException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_ENCODE_CERT", e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_ENCODING_ISSUED_CERT")); + } + + return; + } + + private ICertRecord getCertRecord(BigInteger seq, String certtype[]) + throws EBaseException { + ICertRecord rec = null; + + try { + rec = (ICertRecord) mCertDB.readCertificateRecord(seq); + X509CertImpl x509cert = rec.getCertificate(); + + if (x509cert != null) { + certtype[0] = "x509"; + return rec; + } + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_DISP_BY_SERIAL", e.toString())); + throw e; + } + + return rec; + } + + private BigInteger getSerialNumber(HttpServletRequest req) + throws NumberFormatException { + String serialNumString = req.getParameter("serialNumber"); + + if (serialNumString != null) { + serialNumString = serialNumString.trim(); + if (serialNumString.startsWith("0x") || serialNumString.startsWith("0X")) { + return new BigInteger(serialNumString.substring(2), 16); + } else { + return new BigInteger(serialNumString); + } + } else { + throw new NumberFormatException(); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DisplayCRL.java b/base/common/src/com/netscape/cms/servlet/cert/DisplayCRL.java new file mode 100644 index 000000000..ad503272a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DisplayCRL.java @@ -0,0 +1,481 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRLException; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CRLImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.ICRLPrettyPrint; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.dbs.crldb.ICRLRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Utils; + +/** + * Decode the CRL and display it to the requester. + * + * @version $Revision$, $Date$ + */ +public class DisplayCRL extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1152016798229054027L; + private final static String INFO = "DisplayCRL"; + private final static String TPL_FILE = "displayCRL.template"; + //private final static String E_TPL_FILE = "error.template"; + //private final static String OUT_ERROR = "errorDetails"; + + private String mFormPath = null; + private ICertificateAuthority mCA = null; + + /** + * Constructs DisplayCRL servlet. + */ + public DisplayCRL() { + super(); + } + + /** + * Initialize the servlet. This servlet uses the 'displayCRL.template' file to + * to render the response to the client. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + if (mAuthority instanceof ICertificateAuthority) { + mCA = (ICertificateAuthority) mAuthority; + } + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Process the HTTP request + * <ul> + * <li>http.param crlIssuingPoint number + * <li>http.param crlDisplayType entireCRL or crlHeader or base64Encoded or deltaCRL + * <li>http.param pageStart which page to start displaying from + * <li>http.param pageSize number of entries to show per page + * </ul> + * + * @param cmsReq the Request to service. + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE_1", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + // Note error is covered in the same template as success. + + String crlIssuingPointId = req.getParameter("crlIssuingPoint"); + + process(argSet, header, req, resp, crlIssuingPointId, + locale[0]); + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } + + /** + * Display information about a particular CRL. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + HttpServletRequest req, + HttpServletResponse resp, + String crlIssuingPointId, + Locale locale) { + ICRLIssuingPoint crlIP = null; + X509CRLImpl crl = null; + boolean clonedCA = false; + boolean isCRLCacheEnabled = false; + String masterHost = null; + String masterPort = null; + Vector<String> ipNames = null; + String ipId = crlIssuingPointId; + ICRLRepository crlRepository = mCA.getCRLRepository(); + + try { + masterHost = CMS.getConfigStore().getString("master.ca.agent.host", ""); + masterPort = CMS.getConfigStore().getString("master.ca.agent.port", ""); + if (masterHost != null && masterHost.length() > 0 && + masterPort != null && masterPort.length() > 0) { + clonedCA = true; + ipNames = crlRepository.getIssuingPointsNames(); + } + } catch (EBaseException e) { + } + + if (clonedCA) { + if (crlIssuingPointId != null) { + if (ipNames != null && ipNames.size() > 0) { + int i; + for (i = 0; i < ipNames.size(); i++) { + String ipName = ipNames.elementAt(i); + if (crlIssuingPointId.equals(ipName)) { + break; + } + } + if (i >= ipNames.size()) + crlIssuingPointId = null; + } else { + crlIssuingPointId = null; + } + } + } else { + if (crlIssuingPointId != null) { + Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = ips.nextElement(); + + if (crlIssuingPointId.equals(ip.getId())) { + crlIP = ip; + isCRLCacheEnabled = ip.isCRLCacheEnabled(); + break; + } + if (!ips.hasMoreElements()) + crlIssuingPointId = null; + } + } + } + if (crlIssuingPointId == null) { + header.addStringValue("error", + "Request to unspecified or non-existing CRL issuing point: " + ipId); + return; + } + + ICRLIssuingPointRecord crlRecord = null; + + String crlDisplayType = req.getParameter("crlDisplayType"); + + if (crlDisplayType == null) + crlDisplayType = "cachedCRL"; + header.addStringValue("crlDisplayType", crlDisplayType); + + try { + crlRecord = + (ICRLIssuingPointRecord) mCA.getCRLRepository().readCRLIssuingPointRecord(crlIssuingPointId); + } catch (EBaseException e) { + header.addStringValue("error", e.toString(locale)); + return; + } + if (crlRecord == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlIssuingPointId)); + header.addStringValue("error", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString()); + return; + } + + header.addStringValue("crlIssuingPoint", crlIssuingPointId); + if (crlDisplayType.equals("deltaCRL")) { + if (clonedCA) { + header.addStringValue("crlNumber", crlRecord.getDeltaCRLNumber().toString()); + } else { + header.addStringValue("crlNumber", crlIP.getDeltaCRLNumber().toString()); + } + } else { + if (clonedCA) { + header.addStringValue("crlNumber", crlRecord.getCRLNumber().toString()); + } else { + header.addStringValue("crlNumber", crlIP.getCRLNumber().toString()); + } + } + long lCRLSize = crlRecord.getCRLSize().longValue(); + header.addLongValue("crlSize", lCRLSize); + + if (crlIP != null) { + header.addStringValue("crlDescription", crlIP.getDescription()); + } + + if (!crlDisplayType.equals("cachedCRL")) { + byte[] crlbytes = crlRecord.getCRL(); + + if (crlbytes == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlIssuingPointId)); + header.addStringValue("error", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString()); + return; + } + + try { + if (crlDisplayType.equals("crlHeader")) { + crl = new X509CRLImpl(crlbytes, false); + } else { + crl = new X509CRLImpl(crlbytes); + } + + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_CRL", e.toString())); + header.addStringValue("error", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString()); + } + } + + if (crl != null || (isCRLCacheEnabled && crlDisplayType.equals("cachedCRL"))) { + if (crlDisplayType.equals("entireCRL") || crlDisplayType.equals("cachedCRL")) { + ICRLPrettyPrint crlDetails = null; + if (crlDisplayType.equals("entireCRL")) { + crlDetails = CMS.getCRLPrettyPrint(crl); + } else { + crlDetails = CMS.getCRLCachePrettyPrint(crlIP); + } + + String pageStart = req.getParameter("pageStart"); + String pageSize = req.getParameter("pageSize"); + + if (pageStart != null && pageSize != null) { + long lPageStart = new Long(pageStart).longValue(); + long lPageSize = new Long(pageSize).longValue(); + + if (lPageStart < 1) + lPageStart = 1; + // if (lPageStart + lPageSize - lCRLSize > 1) + // lPageStart = lCRLSize - lPageSize + 1; + + header.addStringValue( + "crlPrettyPrint", crlDetails.toString(locale, + lCRLSize, lPageStart, lPageSize)); + header.addLongValue("pageStart", lPageStart); + header.addLongValue("pageSize", lPageSize); + } else { + header.addStringValue( + "crlPrettyPrint", crlDetails.toString(locale)); + } + } else if (crlDisplayType.equals("crlHeader")) { + ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(crl); + + header.addStringValue( + "crlPrettyPrint", crlDetails.toString(locale, lCRLSize, 0, 0)); + } else if (crlDisplayType.equals("base64Encoded")) { + try { + byte[] ba = crl.getEncoded(); + String crlBase64Encoded = Utils.base64encode(ba); + int length = crlBase64Encoded.length(); + int i = 0; + int j = 0; + int n = 1; + + while (i < length) { + int k = crlBase64Encoded.indexOf('\n', i); + + if (n < 100 && k > -1) { + n++; + i = k + 1; + if (i >= length) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k)); + argSet.addRepeatRecord(rarg); + } + } else { + n = 1; + IArgBlock rarg = CMS.createArgBlock(); + + if (k > -1) { + rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k)); + i = k + 1; + j = i; + } else { + rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, length)); + i = length; + } + argSet.addRepeatRecord(rarg); + } + } + } catch (CRLException e) { + } + } else if (crlDisplayType.equals("deltaCRL")) { + if ((clonedCA && crlRecord.getDeltaCRLSize() != null && + crlRecord.getDeltaCRLSize().longValue() > -1) || + (crlIP != null && crlIP.isDeltaCRLEnabled())) { + byte[] deltaCRLBytes = crlRecord.getDeltaCRL(); + + if (deltaCRLBytes == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_NO_DELTA_CRL", crlIssuingPointId)); + header.addStringValue("error", "Delta CRL is not available"); + } else { + X509CRLImpl deltaCRL = null; + + try { + deltaCRL = new X509CRLImpl(deltaCRLBytes); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_DELTA_CRL", e.toString())); + header.addStringValue("error", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")) + .toString()); + } + if (deltaCRL != null) { + BigInteger crlNumber = crlRecord.getCRLNumber(); + BigInteger deltaNumber = crlRecord.getDeltaCRLNumber(); + if ((clonedCA && crlNumber != null && deltaNumber != null && + deltaNumber.compareTo(crlNumber) >= 0) || + (crlIP != null && crlIP.isThisCurrentDeltaCRL(deltaCRL))) { + + header.addIntegerValue("deltaCRLSize", + deltaCRL.getNumberOfRevokedCertificates()); + + ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(deltaCRL); + + header.addStringValue( + "crlPrettyPrint", crlDetails.toString(locale, 0, 0, 0)); + + try { + byte[] ba = deltaCRL.getEncoded(); + String crlBase64Encoded = Utils.base64encode(ba); + int length = crlBase64Encoded.length(); + int i = 0; + int j = 0; + int n = 1; + + while (i < length) { + int k = crlBase64Encoded.indexOf('\n', i); + + if (n < 100 && k > -1) { + n++; + i = k + 1; + if (i >= length) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("crlBase64Encoded", + crlBase64Encoded.substring(j, k)); + argSet.addRepeatRecord(rarg); + } + } else { + n = 1; + IArgBlock rarg = CMS.createArgBlock(); + + if (k > -1) { + rarg.addStringValue("crlBase64Encoded", + crlBase64Encoded.substring(j, k)); + i = k + 1; + j = i; + } else { + rarg.addStringValue("crlBase64Encoded", + crlBase64Encoded.substring(j, length)); + i = length; + } + argSet.addRepeatRecord(rarg); + } + } + } catch (CRLException e) { + } + } else { + header.addStringValue("error", "Current Delta CRL is not available."); + } + } + } + } else { + header.addStringValue("error", "Delta CRL is not enabled for " + + crlIssuingPointId + + " issuing point"); + } + } + + } else if (!isCRLCacheEnabled && crlDisplayType.equals("cachedCRL")) { + header.addStringValue("error", + CMS.getUserMessage(locale, "CMS_GW_CRL_CACHE_IS_NOT_ENABLED", crlIssuingPointId)); + header.addStringValue("crlPrettyPrint", + CMS.getUserMessage(locale, "CMS_GW_CRL_CACHE_IS_NOT_ENABLED", crlIssuingPointId)); + } else { + header.addStringValue("error", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString()); + header.addStringValue("crlPrettyPrint", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString()); + } + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java b/base/common/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java new file mode 100644 index 000000000..99082d4c5 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java @@ -0,0 +1,227 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Date; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.cms.authentication.HashAuthentication; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Servlet to report the status, ie, the agent-initiated user + * enrollment is enabled or disabled. + * + * @version $Revision$, $Date$ + */ +public class DisplayHashUserEnroll extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -7063912475278810362L; + private final static String TPL_FILE = "/ra/hashDirUserEnroll.template"; + private final static String TPL_ERROR_FILE = "/ra/GenErrorHashDirEnroll.template"; + private String mFormPath = null; + + public DisplayHashUserEnroll() { + super(); + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + try { + mFormPath = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE); + if (mFormPath == null) + mFormPath = TPL_FILE; + } catch (Exception e) { + } + + mTemplates.remove(CMSRequest.SUCCESS); + } + + protected CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Services the request + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String reqHost = httpReq.getRemoteHost(); + + if (!(mAuthority instanceof IRegistrationAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IConfigStore configStore = CMS.getConfigStore(); + String val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr; + boolean isEnable = mgr.isEnable(reqHost); + + if (!isEnable) { + printError(cmsReq, "0"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + Date date = new Date(); + long currTime = date.getTime(); + long timeout = mgr.getTimeout(reqHost); + long lastlogin = mgr.getLastLogin(reqHost); + long diff = currTime - lastlogin; + + if (lastlogin == 0) + mgr.setLastLogin(reqHost, currTime); + else if (diff > timeout) { + mgr.disable(reqHost); + printError(cmsReq, "2"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + mgr.setLastLogin(reqHost, currTime); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + private void printError(CMSRequest cmsReq, String errorCode) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + mTemplates.remove(CMSRequest.SUCCESS); + header.addStringValue("authority", "Registration Manager"); + header.addStringValue("errorCode", errorCode); + String formPath = TPL_ERROR_FILE; + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(formPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_GET_TEMPLATE", formPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); + + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java b/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java new file mode 100644 index 000000000..1594c5323 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java @@ -0,0 +1,1221 @@ +// --- 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.cert; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.InvalidityDateExtension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.usrgrp.Certificates; +import com.netscape.certsrv.usrgrp.ICertUserLocator; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Revoke a Certificate + * + * @version $Revision$, $Date$ + */ +public class DoRevoke extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1693115906265904238L; + private final static String INFO = "DoRevoke"; + private final static String TPL_FILE = "revocationResult.template"; + + private ICertificateRepository mCertDB = null; + private String mFormPath = null; + private IRequestQueue mQueue = null; + private IPublisherProcessor mPublisherProcessor = null; + private Nonces mNonces = null; + private int mTimeLimits = 30; /* in seconds */ + private IUGSubsystem mUG = null; + private ICertUserLocator mUL = null; + + private final static String REVOKE = "revoke"; + private final static String ON_HOLD = "on-hold"; + private final static int ON_HOLD_REASON = 6; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7"; + + public DoRevoke() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template + * file "revocationResult.template" to render the result + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mUG = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + mUL = mUG.getCertUserLocator(); + + if (mAuthority instanceof ICertificateAuthority) { + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + if (((ICertificateAuthority) mAuthority).noncesEnabled()) { + mNonces = ((ICertificateAuthority) mAuthority).getNonces(); + } + } + if (mAuthority instanceof ICertAuthority) { + mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor(); + } + mQueue = mAuthority.getRequestQueue(); + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + /* Server-Side time limit */ + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + } + + /** + * Serves HTTP request. The http parameters used by this request are as follows: + * + * <pre> + * serialNumber Serial number of certificate to revoke (in HEX) + * revocationReason Revocation reason (Described below) + * totalRecordCount [number] + * verifiedRecordCount [number] + * invalidityDate [number of seconds in Jan 1,1970] + * + * </pre> + * + * revocationReason can be one of these values: + * + * <pre> + * 0 = Unspecified (default) + * 1 = Key compromised + * 2 = CA key compromised + * 3 = Affiliation changed + * 4 = Certificate superseded + * 5 = Cessation of operation + * 6 = Certificate is on hold + * </pre> + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + String revokeAll = null; + int totalRecordCount = -1; + int verifiedRecordCount = -1; + EBaseException error = null; + int reason = -1; + boolean authorized = true; + Date invalidityDate = null; + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + try { + if (req.getParameter("revocationReason") != null) { + reason = Integer.parseInt(req.getParameter( + "revocationReason")); + } + if (req.getParameter("totalRecordCount") != null) { + totalRecordCount = Integer.parseInt(req.getParameter( + "totalRecordCount")); + } + if (req.getParameter("verifiedRecordCount") != null) { + verifiedRecordCount = Integer.parseInt( + req.getParameter( + "verifiedRecordCount")); + } + if (req.getParameter("invalidityDate") != null) { + long l = Long.parseLong(req.getParameter( + "invalidityDate")); + + if (l > 0) { + invalidityDate = new Date(l); + } + } + revokeAll = req.getParameter("revokeAll"); + + if (mNonces != null) { + boolean nonceVerified = false; + boolean skipNonceVerification = false; + + X509Certificate cert2 = getSSLClientCertificate(req); + if (cert2 != null) { + X509Certificate certChain[] = new X509Certificate[1]; + certChain[0] = cert2; + IUser user = null; + try { + user = (IUser) mUL.locateUser(new Certificates(certChain)); + } catch (Exception e) { + CMS.debug("DoRevoke: Failed to map certificate '" + + cert2.getSubjectDN().getName() + "' to user."); + } + if (mUG.isMemberOf(user, "Subsystem Group")) { + skipNonceVerification = true; + } + } + + String nonceStr = req.getParameter("nonce"); + if (nonceStr != null) { + long nonce = Long.parseLong(nonceStr.trim()); + X509Certificate cert1 = mNonces.getCertificate(nonce); + if (cert1 == null) { + CMS.debug("DoRevoke: Unknown nonce"); + } else if (cert1 != null && cert2 != null && cert1.equals(cert2)) { + nonceVerified = true; + mNonces.removeNonce(nonce); + } + } else { + CMS.debug("DoRevoke: Missing nonce"); + } + CMS.debug("DoRevoke: nonceVerified=" + nonceVerified); + CMS.debug("DoRevoke: skipNonceVerification=" + skipNonceVerification); + if ((!nonceVerified) && (!skipNonceVerification)) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + } + + String comments = req.getParameter(IRequest.REQUESTOR_COMMENTS); + String eeSubjectDN = null; + String eeSerialNumber = null; + + //for audit log. + String initiative = null; + + String authMgr = AuditFormat.NOAUTH; + + authToken = authenticate(req); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "revoke"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + if (authToken != null) { + + String serialNumber = req.getParameter("serialNumber"); + getSSLClientCertificate(req); // throw exception on error + + if (serialNumber != null) { + eeSerialNumber = serialNumber; + } + + authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + String agentID = authToken.getInString("userid"); + + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID + + " authenticated by " + authMgr; + } + } else { + // request is fromUser. + initiative = AuditFormat.FROMUSER; + + String serialNumber = req.getParameter("serialNumber"); + X509CertImpl sslCert = (X509CertImpl) getSSLClientCertificate(req); + + if (serialNumber == null || sslCert == null || + !(serialNumber.equals(sslCert.getSerialNumber().toString(16)))) { + authorized = false; + } else { + eeSubjectDN = sslCert.getSubjectDN().toString(); + eeSerialNumber = sslCert.getSerialNumber().toString(); + } + + } + + if (authorized) { + process(argSet, header, reason, invalidityDate, initiative, + req, resp, verifiedRecordCount, revokeAll, + totalRecordCount, eeSerialNumber, eeSubjectDN, + comments, locale[0]); + } + + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + error = new EBaseException(CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } + + /* + catch (Exception e) { + noError = false; + header.addStringValue(OUT_ERROR, + MessageFormatter.getLocalizedString( + errorlocale[0], + BaseResources.class.getName(), + BaseResources.INTERNAL_ERROR_1, + e.toString())); + } + */ + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null && authorized) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else if (!authorized) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } + + /** + * Process cert status change request + * <P> + * + * (Certificate Request - either an "agent" cert status change request, or an "EE" cert status change request) + * <P> + * + * (Certificate Request Processed - either an "agent" cert status change request, or an "EE" cert status change + * request) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. - + * "revocation") is made (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is + * changed (revoked, expired, on-hold, off-hold) + * </ul> + * + * @param argSet CMS template parameters + * @param header argument block + * @param reason revocation reason (0 - Unspecified, 1 - Key compromised, + * 2 - CA key compromised; should not be used, 3 - Affiliation changed, + * 4 - Certificate superceded, 5 - Cessation of operation, or + * 6 - Certificate is on hold) + * @param invalidityDate certificate validity date + * @param initiative string containing the audit format + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param verifiedRecordCount number of verified records + * @param revokeAll string containing information on all of the + * certificates to be revoked + * @param totalRecordCount total number of records (verified and unverified) + * @param eeSerialNumber string containing the end-entity certificate + * serial number + * @param eeSubjectDN string containing the end-entity certificate subject + * distinguished name (DN) + * @param comments string containing certificate comments + * @param locale the system locale + * @exception EBaseException an error has occurred + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + int reason, Date invalidityDate, + String initiative, + HttpServletRequest req, + HttpServletResponse resp, + int verifiedRecordCount, + String revokeAll, + int totalRecordCount, + String eeSerialNumber, + String eeSubjectDN, + String comments, + Locale locale) + throws EBaseException { + boolean auditRequest = true; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditSerialNumber = auditSerialNumber(eeSerialNumber); + String auditRequestType = auditRequestType(reason); + String auditApprovalStatus = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditReasonNum = String.valueOf(reason); + + CMS.debug("DoRevoke: eeSerialNumber: " + eeSerialNumber + " auditSerialNumber: " + auditSerialNumber); + long startTime = CMS.getCurrentDate().getTime(); + + try { + int count = 0; + Vector<X509CertImpl> oldCertsV = new Vector<X509CertImpl>(); + Vector<RevokedCertImpl> revCertImplsV = new Vector<RevokedCertImpl>(); + + // Construct a CRL reason code extension. + RevocationReason revReason = RevocationReason.fromInt(reason); + CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revReason); + + // Construct a CRL invalidity date extension. + InvalidityDateExtension invalidityDateExtn = null; + + if (invalidityDate != null) { + invalidityDateExtn = new InvalidityDateExtension(invalidityDate); + } + + // Construct a CRL extension for this request. + CRLExtensions entryExtn = new CRLExtensions(); + + if (crlReasonExtn != null) { + entryExtn.set(crlReasonExtn.getName(), crlReasonExtn); + } + if (invalidityDateExtn != null) { + entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn); + } + + if (mAuthority instanceof ICertificateAuthority) { + + Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll, + totalRecordCount, mTimeLimits); + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = e.nextElement(); + + if (rec == null) + continue; + X509CertImpl xcert = rec.getCertificate(); + IArgBlock rarg = CMS.createArgBlock(); + + // we do not want to revoke the CA certificate accidentially + if (xcert != null && isSystemCertificate(xcert.getSerialNumber())) { + CMS.debug("DoRevoke: skipped revocation request for system certificate " + + xcert.getSerialNumber()); + continue; + } + + if (xcert != null) { + rarg.addStringValue("serialNumber", + xcert.getSerialNumber().toString(16)); + + if (eeSerialNumber != null && + (eeSerialNumber.equals(xcert.getSerialNumber().toString())) && + rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CA_CERTIFICATE_ALREADY_REVOKED_1", xcert.getSerialNumber() + .toString(16))); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getLogMessage("CMSGW_UNAUTHORIZED")); + } else if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + rarg.addStringValue("error", "Certificate 0x" + + xcert.getSerialNumber().toString(16) + + " is already revoked."); + } else if (eeSubjectDN != null && + (!eeSubjectDN.equals(xcert.getSubjectDN().toString()))) { + rarg.addStringValue("error", "Certificate 0x" + + xcert.getSerialNumber().toString(16) + + " belongs to different subject."); + } else { + oldCertsV.addElement(xcert); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(xcert.getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + } + argSet.addRepeatRecord(rarg); + } + } + + } else if (mAuthority instanceof IRegistrationAuthority) { + String reqIdStr = req.getParameter("requestId"); + Vector<String> serialNumbers = new Vector<String>(); + + if (revokeAll != null && revokeAll.length() > 0) { + for (int i = revokeAll.indexOf('='); i < revokeAll.length() && i > -1; + i = revokeAll.indexOf('=', i)) { + if (i > -1) { + i++; + while (i < revokeAll.length() && revokeAll.charAt(i) == ' ') { + i++; + } + // xxxx decimal serial number? + String legalDigits = "0123456789"; + int j = i; + + while (j < revokeAll.length() && legalDigits.indexOf(revokeAll.charAt(j)) != -1) { + j++; + } + if (j > i) { + serialNumbers.addElement(revokeAll.substring(i, j)); + } + } + } + } + if (reqIdStr != null && reqIdStr.length() > 0 && serialNumbers.size() > 0) { + IRequest certReq = mRequestQueue.findRequest(new RequestId(reqIdStr)); + X509CertImpl[] certs = certReq.getExtDataInCertArray(IRequest.OLD_CERTS); + boolean authorized = false; + + for (int i = 0; i < certs.length; i++) { + boolean addToList = false; + + for (int j = 0; j < serialNumbers.size(); j++) { + //xxxxx serial number in decimal? + if (certs[i].getSerialNumber().toString().equals((String) serialNumbers.elementAt(j)) && + eeSubjectDN != null && eeSubjectDN.equals(certs[i].getSubjectDN().toString())) { + addToList = true; + break; + } + } + if (eeSerialNumber != null && + eeSerialNumber.equals(certs[i].getSerialNumber().toString())) { + authorized = true; + } + if (addToList) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("serialNumber", + certs[i].getSerialNumber().toString(16)); + oldCertsV.addElement(certs[i]); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(certs[i].getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + argSet.addRepeatRecord(rarg); + } + } + if (!authorized) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQ_AUTH_REVOKED_CERT")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getLogMessage("CMSGW_UNAUTHORIZED")); + } + } else { + String b64eCert = req.getParameter("b64eCertificate"); + + if (b64eCert != null) { + // BASE64Decoder decoder = new BASE64Decoder(); + // byte[] certBytes = decoder.decodeBuffer(b64eCert); + byte[] certBytes = CMS.AtoB(b64eCert); + X509CertImpl cert = new X509CertImpl(certBytes); + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("serialNumber", + cert.getSerialNumber().toString(16)); + oldCertsV.addElement(cert); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(cert.getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + count++; + rarg.addStringValue("error", null); + argSet.addRepeatRecord(rarg); + } + } + } + if (count == 0) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REV_CERTS_ZERO")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getLogMessage("CMSGW_REVOCATION_ERROR_CERT_NOT_FOUND")); + } + + header.addIntegerValue("totalRecordCount", count); + + X509CertImpl[] oldCerts = new X509CertImpl[count]; + //Certificate[] oldCerts = new Certificate[count]; + RevokedCertImpl[] revCertImpls = new RevokedCertImpl[count]; + + for (int i = 0; i < count; i++) { + oldCerts[i] = (X509CertImpl) oldCertsV.elementAt(i); + revCertImpls[i] = (RevokedCertImpl) revCertImplsV.elementAt(i); + } + + IRequest revReq = + mQueue.newRequest(IRequest.REVOCATION_REQUEST); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + revReq.setExtData(IRequest.CERT_INFO, revCertImpls); + revReq.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST); + if (initiative.equals(AuditFormat.FROMUSER)) + revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_EE); + else + revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT); + revReq.setExtData(IRequest.OLD_CERTS, oldCerts); + if (comments != null) { + revReq.setExtData(IRequest.REQUESTOR_COMMENTS, comments); + } + revReq.setExtData(IRequest.REVOKED_REASON, + Integer.valueOf(reason)); + + // change audit processing from "REQUEST" to "REQUEST_PROCESSED" + // to distinguish which type of signed audit log message to save + // as a failure outcome in case an exception occurs + auditRequest = false; + + mQueue.processRequest(revReq); + + // retrieve the request status + auditApprovalStatus = revReq.getRequestStatus().toString(); + + RequestStatus stat = revReq.getRequestStatus(); + String type = revReq.getRequestType(); + + // The SVC_PENDING check has been added for the Cloned CA request + // that is meant for the Master CA. From Clone's point of view + // the request is complete + if ((stat == RequestStatus.COMPLETE) + || ((type.equals(IRequest.CLA_CERT4CRL_REQUEST)) && (stat == RequestStatus.SVC_PENDING))) { + // audit log the error + Integer result = revReq.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + String[] svcErrors = + revReq.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + //cmsReq.setErrorDescription(err); + for (int j = 0; j < count; j++) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed with error: " + + err, + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + } + } + + // store a message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + + return; + } + + long endTime = CMS.getCurrentDate().getTime(); + + // audit log the success. + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed", + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() + + " time: " + (endTime - startTime) } + ); + } + } + } + + header.addStringValue("revoked", "yes"); + + Integer updateCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS); + + if (updateCRLResult != null) { + header.addStringValue("updateCRL", "yes"); + if (updateCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("updateCRLSuccess", "yes"); + } else { + header.addStringValue("updateCRLSuccess", "no"); + String crlError = + revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR); + + if (crlError != null) + header.addStringValue("updateCRLError", + crlError); + } + // let known crl publishing status too. + Integer publishCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS); + + if (publishCRLResult != null) { + if (publishCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("publishCRLSuccess", "yes"); + } else { + header.addStringValue("publishCRLSuccess", "no"); + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) + header.addStringValue("publishCRLError", + publError); + } + } + } + + if (mAuthority instanceof ICertificateAuthority) { + // let known update and publish status of all crls. + Enumeration<ICRLIssuingPoint> otherCRLs = + ((ICertificateAuthority) mAuthority).getCRLIssuingPoints(); + + while (otherCRLs.hasMoreElements()) { + ICRLIssuingPoint crl = (ICRLIssuingPoint) + otherCRLs.nextElement(); + String crlId = crl.getId(); + + if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL)) + continue; + String updateStatusStr = crl.getCrlUpdateStatusStr(); + Integer updateResult = revReq.getExtDataInInteger(updateStatusStr); + + if (updateResult != null) { + if (updateResult.equals(IRequest.RES_SUCCESS)) { + CMS.debug("DoRevoke: " + + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER", updateStatusStr)); + header.addStringValue(updateStatusStr, "yes"); + } else { + String updateErrorStr = crl.getCrlUpdateErrorStr(); + + CMS.debug("DoRevoke: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO", + updateStatusStr)); + header.addStringValue(updateStatusStr, "no"); + String error = + revReq.getExtDataInString(updateErrorStr); + + if (error != null) + header.addStringValue(updateErrorStr, + error); + } + String publishStatusStr = crl.getCrlPublishStatusStr(); + Integer publishResult = + revReq.getExtDataInInteger(publishStatusStr); + + if (publishResult == null) + continue; + if (publishResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue(publishStatusStr, "yes"); + } else { + String publishErrorStr = + crl.getCrlPublishErrorStr(); + + header.addStringValue(publishStatusStr, "no"); + String error = + revReq.getExtDataInString(publishErrorStr); + + if (error != null) + header.addStringValue( + publishErrorStr, error); + } + } + } + } + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + header.addStringValue("dirEnabled", "yes"); + Integer[] ldapPublishStatus = + revReq.getExtDataInIntegerArray("ldapPublishStatus"); + int certsToUpdate = 0; + int certsUpdated = 0; + + if (ldapPublishStatus != null) { + certsToUpdate = ldapPublishStatus.length; + for (int i = 0; i < certsToUpdate; i++) { + if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) { + certsUpdated++; + } + } + } + header.addIntegerValue("certsUpdated", certsUpdated); + header.addIntegerValue("certsToUpdate", certsToUpdate); + + // add crl publishing status. + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) { + header.addStringValue("crlPublishError", + publError); + } + } else { + header.addStringValue("dirEnabled", "no"); + } + header.addStringValue("error", null); + + } else { + if (stat == RequestStatus.PENDING || stat == RequestStatus.REJECTED) { + header.addStringValue("revoked", stat.toString()); + } else { + header.addStringValue("revoked", "no"); + } + Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS); + if (errors != null) { + StringBuffer errInfo = new StringBuffer(); + for (int i = 0; i < errors.size(); i++) { + errInfo.append(errors.elementAt(i)); + errInfo.append("\n"); + } + header.addStringValue("error", errInfo.toString()); + + } else if (stat == RequestStatus.PENDING) { + header.addStringValue("error", "Request Pending"); + } else { + header.addStringValue("error", null); + } + + // audit log the pending, revoked and rest + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + stat.toString(), + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + + // store a message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + + } catch (CertificateException e) { + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + log(ILogger.LL_FAILURE, "error " + e); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, "error " + e); + + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + throw e; + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED_1", e.toString())); + + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED")); + } + + return; + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @param req HTTP request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = null; + + // Obtain the requesterID + requesterID = req.getParameter("requestId"); + + if (requesterID != null) { + requesterID = requesterID.trim(); + } else { + requesterID = ILogger.UNIDENTIFIED; + } + + return requesterID; + } + + /** + * Signed Audit Log Serial Number + * + * This method is called to obtain the serial number of the certificate + * whose status is to be changed for a signed audit log message. + * <P> + * + * @param eeSerialNumber a string containing the un-normalized serialNumber + * @return id string containing the signed audit log message RequesterID + */ + private String auditSerialNumber(String eeSerialNumber) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String serialNumber = null; + + // Normalize the serialNumber + if (eeSerialNumber != null) { + serialNumber = eeSerialNumber.trim(); + + // find out if the value is hex or decimal + + BigInteger value = BigInteger.ONE.negate(); + + //try int + try { + value = new BigInteger(serialNumber, 10); + } catch (NumberFormatException e) { + } + + //try hex + if (value.compareTo(BigInteger.ONE.negate()) == 0) { + try { + value = new BigInteger(serialNumber, 16); + } catch (NumberFormatException e) { + } + } + // give up if it isn't hex or dec + if (value.compareTo(BigInteger.ONE.negate()) == 0) { + throw new NumberFormatException(); + } + + // convert it to hexadecimal + serialNumber = "0x" + value.toString(16); + } else { + serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + return serialNumber; + } + + /** + * Signed Audit Log Request Type + * + * This method is called to obtain the "Request Type" for + * a signed audit log message. + * <P> + * + * @param reason an integer denoting the revocation reason + * @return string containing REVOKE or ON_HOLD + */ + private String auditRequestType(int reason) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requestType = null; + + // Determine the revocation type based upon the revocation reason + if (reason == ON_HOLD_REASON) { + requestType = ON_HOLD; + } else { + requestType = REVOKE; + } + + return requestType; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java b/base/common/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java new file mode 100644 index 000000000..c4603dd51 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java @@ -0,0 +1,940 @@ +// --- 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.cert; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.InvalidityDateExtension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Revoke a Certificate + * + * @version $Revision$, $Date$ + */ +public class DoRevokeTPS extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -2980600514636454836L; + private final static String INFO = "DoRevoke"; + private final static String TPL_FILE = "revocationResult.template"; + + private ICertificateRepository mCertDB = null; + private String mFormPath = null; + private IRequestQueue mQueue = null; + private IPublisherProcessor mPublisherProcessor = null; + private String errorString = "error="; + private String o_status = "status=0"; + private int mTimeLimits = 30; /* in seconds */ + + private final static String REVOKE = "revoke"; + private final static String ON_HOLD = "on-hold"; + private final static int ON_HOLD_REASON = 6; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7"; + + public DoRevokeTPS() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template + * file "revocationResult.template" to render the result + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + if (mAuthority instanceof ICertificateAuthority) { + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + } + if (mAuthority instanceof ICertAuthority) { + mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor(); + } + mQueue = mAuthority.getRequestQueue(); + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + mRenderResult = false; + + /* Server-Side time limit */ + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + } + + /** + * Serves HTTP request. The http parameters used by this request are as follows: + * + * <pre> + * serialNumber Serial number of certificate to revoke (in HEX) + * revocationReason Revocation reason (Described below) + * totalRecordCount [number] + * verifiedRecordCount [number] + * invalidityDate [number of seconds in Jan 1,1970] + * + * </pre> + * + * revocationReason can be one of these values: + * + * <pre> + * 0 = Unspecified (default) + * 1 = Key compromised + * 2 = CA key compromised + * 3 = Affiliation changed + * 4 = Certificate superseded + * 5 = Cessation of operation + * 6 = Certificate is on hold + * </pre> + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + CMS.debug("DoRevokeTPS after authenticate"); + + String revokeAll = null; + int totalRecordCount = -1; + EBaseException error = null; + int reason = -1; + boolean authorized = true; + Date invalidityDate = null; + Locale[] locale = new Locale[1]; + + CMS.debug("DoRevokeTPS before getTemplate"); + try { + @SuppressWarnings("unused") + CMSTemplate form = getTemplate(mFormPath, req, locale); // check for errors + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } catch (Exception e) { + CMS.debug("DoRevokeTPS getTemplate failed"); + throw new EBaseException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + + CMS.debug("DoRevokeTPS after getTemplate"); + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + try { + if (req.getParameter("revocationReason") != null) { + reason = Integer.parseInt(req.getParameter( + "revocationReason")); + } + if (req.getParameter("totalRecordCount") != null) { + totalRecordCount = Integer.parseInt(req.getParameter( + "totalRecordCount")); + } + if (req.getParameter("invalidityDate") != null) { + long l = Long.parseLong(req.getParameter( + "invalidityDate")); + + if (l > 0) { + invalidityDate = new Date(l); + } + } + revokeAll = req.getParameter("revokeAll"); + String comments = req.getParameter(IRequest.REQUESTOR_COMMENTS); + + //for audit log. + String initiative = null; + + String authMgr = AuditFormat.NOAUTH; + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "revoke"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + if (authToken != null) { + authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + String agentID = authToken.getInString("userid"); + + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID + + " authenticated by " + authMgr; + } + } else { + CMS.debug("DoRevokeTPS: Missing authentication manager"); + o_status = "status=1"; + errorString = "errorString=Missing authentication manager."; + } + + if (authorized) { + process(argSet, header, reason, invalidityDate, initiative, req, + resp, revokeAll, totalRecordCount, comments, locale[0]); + } + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + error = new EBaseException(CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } + + try { + if (!authorized) { + o_status = "status=3"; + errorString = "error=unauthorized"; + } else if (error != null) { + o_status = "status=3"; + errorString = "error=" + error.toString(); + } + + String pp = o_status + "\n" + errorString; + byte[] b = pp.getBytes(); + resp.setContentType("text/html"); + resp.setContentLength(b.length); + OutputStream os = resp.getOutputStream(); + os.write(b); + os.flush(); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } + + /** + * Process cert status change request + * <P> + * + * (Certificate Request - either an "agent" cert status change request, or an "EE" cert status change request) + * <P> + * + * (Certificate Request Processed - either an "agent" cert status change request, or an "EE" cert status change + * request) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. - + * "revocation") is made (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is + * changed (revoked, expired, on-hold, off-hold) + * </ul> + * + * @param argSet CMS template parameters + * @param header argument block + * @param reason revocation reason (0 - Unspecified, 1 - Key compromised, + * 2 - CA key compromised; should not be used, 3 - Affiliation changed, + * 4 - Certificate superceded, 5 - Cessation of operation, or + * 6 - Certificate is on hold) + * @param invalidityDate certificate validity date + * @param initiative string containing the audit format + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param revokeAll string containing information on all of the + * certificates to be revoked + * @param totalRecordCount total number of records (verified and unverified) + * @param comments string containing certificate comments + * @param locale the system locale + * @exception EBaseException an error has occurred + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + int reason, Date invalidityDate, + String initiative, + HttpServletRequest req, + HttpServletResponse resp, + String revokeAll, + int totalRecordCount, + String comments, + Locale locale) + throws EBaseException { + boolean auditRequest = true; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditSerialNumber = auditSerialNumber(null); + String auditRequestType = auditRequestType(reason); + String auditApprovalStatus = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditReasonNum = String.valueOf(reason); + + if (revokeAll != null) { + CMS.debug("DoRevokeTPS.process revokeAll" + revokeAll); + + String serial = ""; + String[] tokens; + tokens = revokeAll.split("="); + + if (tokens.length == 2) { + serial = tokens[1]; + //remove the trailing paren + if (serial.endsWith(")")) { + serial = serial.substring(0, serial.length() - 1); + } + auditSerialNumber = serial; + } + } + + long startTime = CMS.getCurrentDate().getTime(); + + try { + int count = 0; + Vector<X509CertImpl> oldCertsV = new Vector<X509CertImpl>(); + Vector<RevokedCertImpl> revCertImplsV = new Vector<RevokedCertImpl>(); + + // Construct a CRL reason code extension. + RevocationReason revReason = RevocationReason.fromInt(reason); + CRLReasonExtension crlReasonExtn = new CRLReasonExtension(revReason); + + // Construct a CRL invalidity date extension. + InvalidityDateExtension invalidityDateExtn = null; + + if (invalidityDate != null) { + invalidityDateExtn = new InvalidityDateExtension(invalidityDate); + } + + // Construct a CRL extension for this request. + CRLExtensions entryExtn = new CRLExtensions(); + + if (crlReasonExtn != null) { + entryExtn.set(crlReasonExtn.getName(), crlReasonExtn); + } + if (invalidityDateExtn != null) { + entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn); + } + + Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll, + totalRecordCount, mTimeLimits); + + boolean alreadyRevokedCertFound = false; + boolean badCertsRequested = false; + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) e.nextElement(); + + if (rec == null) { + badCertsRequested = true; + continue; + } + X509CertImpl xcert = rec.getCertificate(); + IArgBlock rarg = CMS.createArgBlock(); + + // we do not want to revoke the CA certificate accidentially + if (xcert != null && isSystemCertificate(xcert.getSerialNumber())) { + CMS.debug("DoRevokeTPS: skipped revocation request for system certificate " + + xcert.getSerialNumber()); + badCertsRequested = true; + continue; + } + + if (xcert != null) { + rarg.addStringValue("serialNumber", + xcert.getSerialNumber().toString(16)); + + if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + alreadyRevokedCertFound = true; + CMS.debug("Certificate 0x" + xcert.getSerialNumber().toString(16) + " has been revoked."); + } else { + oldCertsV.addElement(xcert); + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(xcert.getSerialNumber(), + CMS.getCurrentDate(), entryExtn); + + revCertImplsV.addElement(revCertImpl); + CMS.debug("Certificate 0x" + xcert.getSerialNumber().toString(16) + " is going to be revoked."); + count++; + } + } else { + badCertsRequested = true; + } + } + + if (count == 0) { + // Situation where no certs were reoked here, but some certs + // requested happened to be already revoked. Don't return error. + if (alreadyRevokedCertFound == true && badCertsRequested == false) { + CMS.debug("Only have previously revoked certs in the list."); + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + return; + } + + errorString = "error=No certificates are revoked."; + o_status = "status=2"; + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REV_CERTS_ZERO")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED")); + } + + X509CertImpl[] oldCerts = new X509CertImpl[count]; + RevokedCertImpl[] revCertImpls = new RevokedCertImpl[count]; + + for (int i = 0; i < count; i++) { + oldCerts[i] = (X509CertImpl) oldCertsV.elementAt(i); + revCertImpls[i] = (RevokedCertImpl) revCertImplsV.elementAt(i); + } + + IRequest revReq = + mQueue.newRequest(IRequest.REVOCATION_REQUEST); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + revReq.setExtData(IRequest.CERT_INFO, revCertImpls); + revReq.setExtData(IRequest.REQ_TYPE, IRequest.REVOCATION_REQUEST); + if (initiative.equals(AuditFormat.FROMUSER)) { + revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_EE); + } else { + revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT); + } + revReq.setExtData(IRequest.OLD_CERTS, oldCerts); + if (comments != null) { + revReq.setExtData(IRequest.REQUESTOR_COMMENTS, comments); + } + revReq.setExtData(IRequest.REVOKED_REASON, + Integer.valueOf(reason)); + + // change audit processing from "REQUEST" to "REQUEST_PROCESSED" + // to distinguish which type of signed audit log message to save + // as a failure outcome in case an exception occurs + auditRequest = false; + + mQueue.processRequest(revReq); + + // retrieve the request status + auditApprovalStatus = revReq.getRequestStatus().toString(); + + RequestStatus stat = revReq.getRequestStatus(); + String type = revReq.getRequestType(); + + // The SVC_PENDING check has been added for the Cloned CA request + // that is meant for the Master CA. From Clone's point of view + // the request is complete + if ((stat == RequestStatus.COMPLETE) + || ((type.equals(IRequest.CLA_CERT4CRL_REQUEST)) && (stat == RequestStatus.SVC_PENDING))) { + // audit log the error + Integer result = revReq.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + String[] svcErrors = + revReq.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + //cmsReq.setErrorDescription(err); + for (int j = 0; j < count; j++) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed with error: " + + err, + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + } + } + + // store a message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + + return; + } + + long endTime = CMS.getCurrentDate().getTime(); + + // audit log the success. + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + "completed", + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() + + " time: " + (endTime - startTime) } + ); + } + } + } + + header.addStringValue("revoked", "yes"); + + Integer updateCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS); + + if (updateCRLResult != null) { + if (!updateCRLResult.equals(IRequest.RES_SUCCESS)) { + + o_status = "status=3"; + if (revReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR) != null) { + errorString = "error=Update CRL Error."; + // 3 means miscellaneous + } + } + // let known crl publishing status too. + Integer publishCRLResult = + revReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS); + + if (publishCRLResult != null) { + if (!publishCRLResult.equals(IRequest.RES_SUCCESS)) { + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + o_status = "status=3"; + if (publError != null) { + errorString = "error=" + publError; + } + } + } + } + + if (mAuthority instanceof ICertificateAuthority) { + // let known update and publish status of all crls. + Enumeration<ICRLIssuingPoint> otherCRLs = + ((ICertificateAuthority) mAuthority).getCRLIssuingPoints(); + + while (otherCRLs.hasMoreElements()) { + ICRLIssuingPoint crl = (ICRLIssuingPoint) + otherCRLs.nextElement(); + String crlId = crl.getId(); + + if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL)) + continue; + String updateStatusStr = crl.getCrlUpdateStatusStr(); + Integer updateResult = revReq.getExtDataInInteger(updateStatusStr); + + if (updateResult != null) { + if (!updateResult.equals(IRequest.RES_SUCCESS)) { + String updateErrorStr = crl.getCrlUpdateErrorStr(); + + CMS.debug("DoRevoke: " + CMS.getLogMessage("ADMIN_SRVLT_ADDING_HEADER_NO", + updateStatusStr)); + String error = + revReq.getExtDataInString(updateErrorStr); + + o_status = "status=3"; + if (error != null) { + errorString = "error=" + error; + } + } + String publishStatusStr = crl.getCrlPublishStatusStr(); + Integer publishResult = + revReq.getExtDataInInteger(publishStatusStr); + + if (publishResult == null) + continue; + if (!publishResult.equals(IRequest.RES_SUCCESS)) { + String publishErrorStr = + crl.getCrlPublishErrorStr(); + + String error = + revReq.getExtDataInString(publishErrorStr); + + o_status = "status=3"; + if (error != null) { + errorString = "error=Publish CRL Status Error."; + } + } + } + } + } + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + header.addStringValue("dirEnabled", "yes"); + + // add crl publishing status. + String publError = + revReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) { + errorString = "error=" + publError; + o_status = "status=3"; + } + } else if (mPublisherProcessor == null && mPublisherProcessor.ldapEnabled()) { + errorString = "error=LDAP publishing not enabled."; + o_status = "status=3"; + } + } else { + if (stat == RequestStatus.PENDING || stat == RequestStatus.REJECTED) { + o_status = "status=2"; + errorString = "error=" + stat.toString(); + } else { + o_status = "status=2"; + errorString = "error=Undefined request status"; + } + Vector<String> errors = revReq.getExtDataInStringVector(IRequest.ERRORS); + if (errors != null) { + StringBuffer errInfo = new StringBuffer(); + + for (int i = 0; i < errors.size(); i++) { + errInfo.append(errors.elementAt(i)); + errInfo.append("\n"); + } + o_status = "status=2"; + errorString = "error=" + errInfo.toString(); + + } else if (stat == RequestStatus.PENDING) { + o_status = "status=2"; + errorString = "error=Request pending"; + } else { + o_status = "status=2"; + errorString = "error=Undefined request status"; + } + + // audit log the pending, revoked and rest + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + revReq.getRequestId(), + initiative, + stat.toString(), + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + + // store a message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, "error " + e); + + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + throw e; + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED_1", e.toString())); + + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + + throw new ECMSGWException(CMS.getLogMessage("CMSGW_ERROR_MARKING_CERT_REVOKED")); + } + + return; + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @param req HTTP request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = null; + + // Obtain the requesterID + requesterID = req.getParameter("requestId"); + + if (requesterID != null) { + requesterID = requesterID.trim(); + } else { + requesterID = ILogger.UNIDENTIFIED; + } + + return requesterID; + } + + /** + * Signed Audit Log Serial Number + * + * This method is called to obtain the serial number of the certificate + * whose status is to be changed for a signed audit log message. + * <P> + * + * @param eeSerialNumber a string containing the un-normalized serialNumber + * @return id string containing the signed audit log message RequesterID + */ + private String auditSerialNumber(String eeSerialNumber) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String serialNumber = null; + + // Normalize the serialNumber + if (eeSerialNumber != null) { + serialNumber = eeSerialNumber.trim(); + + // convert it to hexadecimal + serialNumber = "0x" + (new BigInteger(serialNumber)).toString(16); + } else { + serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + return serialNumber; + } + + /** + * Signed Audit Log Request Type + * + * This method is called to obtain the "Request Type" for + * a signed audit log message. + * <P> + * + * @param reason an integer denoting the revocation reason + * @return string containing REVOKE or ON_HOLD + */ + private String auditRequestType(int reason) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requestType = null; + + // Determine the revocation type based upon the revocation reason + if (reason == ON_HOLD_REASON) { + requestType = ON_HOLD; + } else { + requestType = REVOKE; + } + + return requestType; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DoUnrevoke.java b/base/common/src/com/netscape/cms/servlet/cert/DoUnrevoke.java new file mode 100644 index 000000000..c6b6065b4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DoUnrevoke.java @@ -0,0 +1,671 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * 'Unrevoke' a certificate. (For certificates that are on-hold only, + * take them off-hold) + * + * @version $Revision$, $Date$ + */ +public class DoUnrevoke extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -7978703730006036625L; + private final static String INFO = "DoUnrevoke"; + private final static String TPL_FILE = "unrevocationResult.template"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + + private ICertificateRepository mCertDB = null; + private String mFormPath = null; + private IRequestQueue mQueue = null; + private IPublisherProcessor mPublisherProcessor = null; + + private final static String OFF_HOLD = "off-hold"; + private final static int OFF_HOLD_REASON = 6; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7"; + + public DoUnrevoke() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mAuthority instanceof ICertificateAuthority) { + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + } + if (mAuthority instanceof ICertAuthority) { + mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor(); + } + mQueue = mAuthority.getRequestQueue(); + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param serialNumber Decimal serial number of certificate to unrevoke. The certificate must be revoked + * with a revovcation reason 'on hold' for this operation to succeed. The serial number may be expressed as a hex + * number by prefixing '0x' to the serialNumber string + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + BigInteger[] serialNumber; + EBaseException error = null; + + CMSTemplate form = null; + + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + try { + serialNumber = getSerialNumbers(req); + + //for audit log. + IAuthToken authToken = authenticate(cmsReq); + String authMgr = AuditFormat.NOAUTH; + + if (authToken != null) { + authMgr = + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } else { + CMS.debug("DoUnrevoke::process() - authToken is null!"); + return; + } + String agentID = authToken.getInString("userid"); + String initiative = AuditFormat.FROMAGENT + " agentID: " + agentID + + " authenticated by " + authMgr; + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "unrevoke"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + process(argSet, header, serialNumber, req, resp, locale[0], initiative); + + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUM_FORMAT")); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Process X509 cert status change request + * <P> + * + * (Certificate Request - an "agent" cert status change request to take a certificate off-hold) + * <P> + * + * (Certificate Request Processed - an "agent" cert status change request to take a certificate off-hold) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. - + * "revocation") is made (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is + * changed (taken off-hold) + * </ul> + * + * @param argSet CMS template parameters + * @param header argument block + * @param serialNumbers the serial number of the certificate + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param locale the system locale + * @param initiative string containing the audit format + * @exception EBaseException an error has occurred + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + BigInteger[] serialNumbers, + HttpServletRequest req, + HttpServletResponse resp, + Locale locale, String initiative) + throws EBaseException { + boolean auditRequest = true; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditSerialNumber = auditSerialNumber(serialNumbers[0].toString()); + String auditRequestType = OFF_HOLD; + String auditApprovalStatus = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditReasonNum = String.valueOf(OFF_HOLD_REASON); + + try { + StringBuffer snList = new StringBuffer(); + + // certs are for old cloning and they should be removed as soon as possible + X509CertImpl[] certs = new X509CertImpl[serialNumbers.length]; + for (int i = 0; i < serialNumbers.length; i++) { + certs[i] = (X509CertImpl) getX509Certificate(serialNumbers[i]); + if (snList.length() > 0) + snList.append(", "); + snList.append("0x"); + snList.append(serialNumbers[i].toString(16)); + } + header.addStringValue("serialNumber", snList.toString()); + + IRequest unrevReq = mQueue.newRequest(IRequest.UNREVOCATION_REQUEST); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + unrevReq.setExtData(IRequest.REQ_TYPE, IRequest.UNREVOCATION_REQUEST); + unrevReq.setExtData(IRequest.OLD_SERIALS, serialNumbers); + unrevReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT); + + // change audit processing from "REQUEST" to "REQUEST_PROCESSED" + // to distinguish which type of signed audit log message to save + // as a failure outcome in case an exception occurs + auditRequest = false; + + mQueue.processRequest(unrevReq); + + // retrieve the request status + auditApprovalStatus = unrevReq.getRequestStatus().toString(); + + RequestStatus status = unrevReq.getRequestStatus(); + String type = unrevReq.getRequestType(); + + if ((status == RequestStatus.COMPLETE) + || ((type.equals(IRequest.CLA_UNCERT4CRL_REQUEST)) && (status == RequestStatus.SVC_PENDING))) { + + Integer result = unrevReq.getExtDataInInteger(IRequest.RESULT); + + if (result != null && result.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("unrevoked", "yes"); + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + "completed", + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + } else { + header.addStringValue("unrevoked", "no"); + String error = unrevReq.getExtDataInString(IRequest.ERROR); + + if (error != null) { + header.addStringValue("error", error); + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + "completed with error: " + + error, + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + + /****************************************************/ + + /* IMPORTANT: In the event that the following */ + + /* "throw error;" statement is */ + + /* uncommented, uncomment the following */ + + /* signed audit log message, also!!! */ + + /****************************************************/ + + // // store a message in the signed audit log file + // // if and only if "auditApprovalStatus" is + // // "complete", "revoked", or "canceled" + // if( ( auditApprovalStatus.equals( + // RequestStatus.COMPLETE_STRING ) ) || + // ( auditApprovalStatus.equals( + // RequestStatus.REJECTED_STRING ) ) || + // ( auditApprovalStatus.equals( + // RequestStatus.CANCELED_STRING ) ) ) { + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + // auditSubjectID, + // ILogger.FAILURE, + // auditRequesterID, + // auditSerialNumber, + // auditRequestType, + // auditReasonNum, + // auditApprovalStatus ); + // + // audit( auditMessage ); + // } + + // throw error; + } + } + + Integer updateCRLResult = + unrevReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS); + + if (updateCRLResult != null) { + header.addStringValue("updateCRL", "yes"); + if (updateCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("updateCRLSuccess", "yes"); + } else { + header.addStringValue("updateCRLSuccess", "no"); + String crlError = + unrevReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR); + + if (crlError != null) + header.addStringValue("updateCRLError", + crlError); + } + // let known crl publishing status too. + Integer publishCRLResult = + unrevReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS); + + if (publishCRLResult != null) { + if (publishCRLResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue("publishCRLSuccess", "yes"); + } else { + header.addStringValue("publishCRLSuccess", "no"); + String publError = + unrevReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) + header.addStringValue("publishCRLError", + publError); + } + } + } + + // let known update and publish status of all crls. + Enumeration<ICRLIssuingPoint> otherCRLs = + ((ICertificateAuthority) mAuthority).getCRLIssuingPoints(); + + while (otherCRLs.hasMoreElements()) { + ICRLIssuingPoint crl = otherCRLs.nextElement(); + String crlId = crl.getId(); + + if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL)) + continue; + String updateStatusStr = crl.getCrlUpdateStatusStr(); + Integer updateResult = unrevReq.getExtDataInInteger(updateStatusStr); + + if (updateResult != null) { + if (updateResult.equals(IRequest.RES_SUCCESS)) { + CMS.debug("DoUnrevoke: adding header " + + updateStatusStr + " yes "); + header.addStringValue(updateStatusStr, "yes"); + } else { + String updateErrorStr = crl.getCrlUpdateErrorStr(); + + CMS.debug("DoUnrevoke: adding header " + + updateStatusStr + " no "); + header.addStringValue(updateStatusStr, "no"); + String error = + unrevReq.getExtDataInString(updateErrorStr); + + if (error != null) + header.addStringValue( + updateErrorStr, error); + } + String publishStatusStr = crl.getCrlPublishStatusStr(); + Integer publishResult = + unrevReq.getExtDataInInteger(publishStatusStr); + + if (publishResult == null) + continue; + if (publishResult.equals(IRequest.RES_SUCCESS)) { + header.addStringValue(publishStatusStr, "yes"); + } else { + String publishErrorStr = + crl.getCrlPublishErrorStr(); + + header.addStringValue(publishStatusStr, "no"); + String error = + unrevReq.getExtDataInString(publishErrorStr); + + if (error != null) + header.addStringValue( + publishErrorStr, error); + } + } + } + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + header.addStringValue("dirEnabled", "yes"); + Integer[] ldapPublishStatus = + unrevReq.getExtDataInIntegerArray("ldapPublishStatus"); + + if (ldapPublishStatus != null) { + if (ldapPublishStatus[0] == IRequest.RES_SUCCESS) { + header.addStringValue("dirUpdated", "yes"); + } else { + header.addStringValue("dirUpdated", "no"); + } + } + } else { + header.addStringValue("dirEnabled", "no"); + } + + } else if (status == RequestStatus.PENDING) { + header.addStringValue("error", "Request Pending"); + header.addStringValue("unrevoked", "pending"); + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + "pending", + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + } else { + header.addStringValue("error", "Request Status.Error"); + header.addStringValue("unrevoked", "no"); + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + status.toString(), + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + } + + // store a message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + + } catch (EBaseException eAudit1) { + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + } + + return; + } + + private BigInteger[] getSerialNumbers(HttpServletRequest req) + throws NumberFormatException { + String serialNumString = req.getParameter("serialNumber"); + + StringTokenizer snList = new StringTokenizer(serialNumString, " "); + Vector<BigInteger> biList = new Vector<BigInteger>(); + while (snList.hasMoreTokens()) { + String snStr = snList.nextToken(); + if (snStr != null) { + snStr = snStr.trim(); + BigInteger bi; + if (snStr.startsWith("0x") || snStr.startsWith("0X")) { + bi = new BigInteger(snStr.substring(2), 16); + } else { + bi = new BigInteger(snStr); + } + if (bi.compareTo(BigInteger.ZERO) < 0) { + throw new NumberFormatException(); + } + biList.addElement(bi); + } else { + throw new NumberFormatException(); + } + } + if (biList.size() < 1) { + throw new NumberFormatException(); + } + + BigInteger[] biNumbers = new BigInteger[biList.size()]; + for (int i = 0; i < biList.size(); i++) { + biNumbers[i] = (BigInteger) biList.elementAt(i); + } + + return biNumbers; + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @param req HTTP request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = null; + + // Obtain the requesterID + requesterID = req.getParameter("requestId"); + + if (requesterID != null) { + requesterID = requesterID.trim(); + } else { + requesterID = ILogger.UNIDENTIFIED; + } + + return requesterID; + } + + /** + * Signed Audit Log Serial Number + * + * This method is called to obtain the serial number of the certificate + * whose status is to be changed for a signed audit log message. + * <P> + * + * @param eeSerialNumber a string containing the un-normalized serialNumber + * @return id string containing the signed audit log message RequesterID + */ + private String auditSerialNumber(String eeSerialNumber) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String serialNumber = null; + + // Normalize the serialNumber + if (eeSerialNumber != null) { + serialNumber = eeSerialNumber.trim(); + + // convert it to hexadecimal + serialNumber = "0x" + (new BigInteger(serialNumber)).toString(16); + } else { + serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + return serialNumber; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java b/base/common/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java new file mode 100644 index 000000000..5d096aff3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java @@ -0,0 +1,618 @@ +// --- 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.cert; + +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * 'Unrevoke' a certificate. (For certificates that are on-hold only, + * take them off-hold) + * + * @version $Revision$, $Date$ + */ +public class DoUnrevokeTPS extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -6245049221697655642L; + private final static String INFO = "DoUnrevoke"; + private final static String TPL_FILE = "unrevocationResult.template"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + + private ICertificateRepository mCertDB = null; + private String mFormPath = null; + private IRequestQueue mQueue = null; + private IPublisherProcessor mPublisherProcessor = null; + private String errorString = "error="; + private String o_status = "status=0"; + + private final static String OFF_HOLD = "off-hold"; + private final static int OFF_HOLD_REASON = 6; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED_7"; + + public DoUnrevokeTPS() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mAuthority instanceof ICertificateAuthority) { + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + } + if (mAuthority instanceof ICertAuthority) { + mPublisherProcessor = ((ICertAuthority) mAuthority).getPublisherProcessor(); + } + mQueue = mAuthority.getRequestQueue(); + + mTemplates.remove(CMSRequest.SUCCESS); + mRenderResult = false; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param serialNumber Decimal serial number of certificate to unrevoke. The certificate must be revoked + * with a revovcation reason 'on hold' for this operation to succeed. The serial number may be expressed as a hex + * number by prefixing '0x' to the serialNumber string + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + BigInteger[] serialNumbers; + EBaseException error = null; + + Locale[] locale = new Locale[1]; + + /* + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + */ + + try { + serialNumbers = getSerialNumbers(req); + + //for audit log. + IAuthToken authToken = authenticate(cmsReq); + String authMgr = AuditFormat.NOAUTH; + + if (authToken != null) { + authMgr = + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } else { + CMS.debug("DoUnrevokeTPS::process() - authToken is null!"); + return; + } + String agentID = authToken.getInString("userid"); + String initiative = AuditFormat.FROMAGENT + " agentID: " + agentID + + " authenticated by " + authMgr; + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "unrevoke"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + o_status = "status=3"; + errorString = "error=unauthorized"; + String pp = o_status + "\n" + errorString; + byte[] b = pp.getBytes(); + resp.setContentType("text/html"); + resp.setContentLength(b.length); + OutputStream os = resp.getOutputStream(); + os.write(b); + os.flush(); + return; + } + + process(serialNumbers, req, resp, locale[0], initiative); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUM_FORMAT")); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } catch (IOException e) { + } + + try { + if (error == null) { + o_status = "status=0"; + errorString = "error="; + } else { + o_status = "status=3"; + errorString = "error=" + error.toString(); + } + + String pp = o_status + "\n" + errorString; + byte[] b = pp.getBytes(); + resp.setContentType("text/html"); + resp.setContentLength(b.length); + OutputStream os = resp.getOutputStream(); + os.write(b); + os.flush(); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Process X509 cert status change request + * <P> + * + * (Certificate Request - an "agent" cert status change request to take a certificate off-hold) + * <P> + * + * (Certificate Request Processed - an "agent" cert status change request to take a certificate off-hold) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST used when a cert status change request (e. g. - + * "revocation") is made (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED used when a certificate status is + * changed (taken off-hold) + * </ul> + * + * @param serialNumbers the serial number of the certificate + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param locale the system locale + * @param initiative string containing the audit format + * @exception EBaseException an error has occurred + */ + private void process(BigInteger[] serialNumbers, + HttpServletRequest req, + HttpServletResponse resp, + Locale locale, String initiative) + throws EBaseException { + boolean auditRequest = true; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = auditRequesterID(req); + String auditSerialNumber = auditSerialNumber(serialNumbers[0].toString()); + String auditRequestType = OFF_HOLD; + String auditApprovalStatus = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditReasonNum = String.valueOf(OFF_HOLD_REASON); + + try { + String snList = ""; + + // certs are for old cloning and they should be removed as soon as possible + X509CertImpl[] certs = new X509CertImpl[serialNumbers.length]; + for (int i = 0; i < serialNumbers.length; i++) { + certs[i] = (X509CertImpl) getX509Certificate(serialNumbers[i]); + if (snList.length() > 0) + snList += ", "; + snList += "0x" + serialNumbers[i].toString(16); + } + + IRequest unrevReq = mQueue.newRequest(IRequest.UNREVOCATION_REQUEST); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + + unrevReq.setExtData(IRequest.REQ_TYPE, IRequest.UNREVOCATION_REQUEST); + unrevReq.setExtData(IRequest.OLD_SERIALS, serialNumbers); + unrevReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT); + + // change audit processing from "REQUEST" to "REQUEST_PROCESSED" + // to distinguish which type of signed audit log message to save + // as a failure outcome in case an exception occurs + auditRequest = false; + + mQueue.processRequest(unrevReq); + + // retrieve the request status + auditApprovalStatus = unrevReq.getRequestStatus().toString(); + + RequestStatus status = unrevReq.getRequestStatus(); + String type = unrevReq.getRequestType(); + + if ((status == RequestStatus.COMPLETE) + || ((type.equals(IRequest.CLA_UNCERT4CRL_REQUEST)) && (status == RequestStatus.SVC_PENDING))) { + + Integer result = unrevReq.getExtDataInInteger(IRequest.RESULT); + + if (result != null && result.equals(IRequest.RES_SUCCESS)) { + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + "completed", + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + } else { + String error = unrevReq.getExtDataInString(IRequest.ERROR); + + if (error != null) { + o_status = "status=3"; + errorString = "error=" + error; + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + "completed with error: " + + error, + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + } + } + + Integer updateCRLResult = + unrevReq.getExtDataInInteger(IRequest.CRL_UPDATE_STATUS); + + if (updateCRLResult != null) { + if (!updateCRLResult.equals(IRequest.RES_SUCCESS)) { + String crlError = + unrevReq.getExtDataInString(IRequest.CRL_UPDATE_ERROR); + + if (crlError != null) { + o_status = "status=3"; + errorString = "error=" + crlError; + } + } + // let known crl publishing status too. + Integer publishCRLResult = + unrevReq.getExtDataInInteger(IRequest.CRL_PUBLISH_STATUS); + + if (publishCRLResult != null) { + if (!publishCRLResult.equals(IRequest.RES_SUCCESS)) { + String publError = + unrevReq.getExtDataInString(IRequest.CRL_PUBLISH_ERROR); + + if (publError != null) { + o_status = "status=3"; + errorString = "error=" + publError; + } + } + } + } + + // let known update and publish status of all crls. + Enumeration<ICRLIssuingPoint> otherCRLs = + ((ICertificateAuthority) mAuthority).getCRLIssuingPoints(); + + while (otherCRLs.hasMoreElements()) { + ICRLIssuingPoint crl = otherCRLs.nextElement(); + String crlId = crl.getId(); + + if (crlId.equals(ICertificateAuthority.PROP_MASTER_CRL)) + continue; + String updateStatusStr = crl.getCrlUpdateStatusStr(); + Integer updateResult = unrevReq.getExtDataInInteger(updateStatusStr); + + if (updateResult != null) { + if (!updateResult.equals(IRequest.RES_SUCCESS)) { + String updateErrorStr = crl.getCrlUpdateErrorStr(); + String error = + unrevReq.getExtDataInString(updateErrorStr); + + if (error != null) { + o_status = "status=3"; + errorString = "error=" + error; + } + } + String publishStatusStr = crl.getCrlPublishStatusStr(); + Integer publishResult = + unrevReq.getExtDataInInteger(publishStatusStr); + + if (publishResult == null) + continue; + if (!publishResult.equals(IRequest.RES_SUCCESS)) { + String publishErrorStr = + crl.getCrlPublishErrorStr(); + + String error = + unrevReq.getExtDataInString(publishErrorStr); + + if (error != null) { + o_status = "status=3"; + errorString = "error=" + error; + } + } + } + } + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + Integer[] ldapPublishStatus = + unrevReq.getExtDataInIntegerArray("ldapPublishStatus"); + + if (ldapPublishStatus != null) { + if (ldapPublishStatus[0] != IRequest.RES_SUCCESS) { + o_status = "status=3"; + errorString = "error=Problem in publishing to LDAP"; + } + } + } else if (mPublisherProcessor == null || (!mPublisherProcessor.ldapEnabled())) { + o_status = "status=3"; + errorString = "error=LDAP Publisher not enabled"; + } + + } else if (status == RequestStatus.PENDING) { + o_status = "status=2"; + errorString = "error=" + status.toString(); + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + "pending", + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + } else { + o_status = "status=2"; + errorString = "error=Undefined request status"; + + if (certs[0] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOUNREVOKEFORMAT, + new Object[] { + unrevReq.getRequestId(), + initiative, + status.toString(), + certs[0].getSubjectDN(), + "0x" + serialNumbers[0].toString(16) } + ); + } + } + + // store a message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals(RequestStatus.COMPLETE_STRING)) + || (auditApprovalStatus.equals(RequestStatus.REJECTED_STRING)) + || (auditApprovalStatus.equals(RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + + } catch (EBaseException eAudit1) { + if (auditRequest) { + // store a "CERT_STATUS_CHANGE_REQUEST" failure + // message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType); + + audit(auditMessage); + } else { + // store a "CERT_STATUS_CHANGE_REQUEST_PROCESSED" failure + // message in the signed audit log file + // if and only if "auditApprovalStatus" is + // "complete", "revoked", or "canceled" + if ((auditApprovalStatus.equals( + RequestStatus.COMPLETE_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.REJECTED_STRING)) || + (auditApprovalStatus.equals( + RequestStatus.CANCELED_STRING))) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_STATUS_CHANGE_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditSerialNumber, + auditRequestType, + auditReasonNum, + auditApprovalStatus); + + audit(auditMessage); + } + } + } + + return; + } + + private BigInteger[] getSerialNumbers(HttpServletRequest req) + throws NumberFormatException { + String serialNumString = req.getParameter("serialNumber"); + + StringTokenizer snList = new StringTokenizer(serialNumString, " "); + Vector<BigInteger> biList = new Vector<BigInteger>(); + while (snList.hasMoreTokens()) { + String snStr = snList.nextToken(); + if (snStr != null) { + snStr = snStr.trim(); + BigInteger bi; + if (snStr.startsWith("0x") || snStr.startsWith("0X")) { + bi = new BigInteger(snStr.substring(2), 16); + } else { + bi = new BigInteger(snStr); + } + if (bi.compareTo(BigInteger.ZERO) < 0) { + throw new NumberFormatException(); + } + biList.addElement(bi); + } else { + throw new NumberFormatException(); + } + } + if (biList.size() < 1) { + throw new NumberFormatException(); + } + + BigInteger[] biNumbers = new BigInteger[biList.size()]; + for (int i = 0; i < biList.size(); i++) { + biNumbers[i] = (BigInteger) biList.elementAt(i); + } + + return biNumbers; + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @param req HTTP request + * @return id string containing the signed audit log message RequesterID + */ + private String auditRequesterID(HttpServletRequest req) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String requesterID = null; + + // Obtain the requesterID + requesterID = req.getParameter("requestId"); + + if (requesterID != null) { + requesterID = requesterID.trim(); + } else { + requesterID = ILogger.UNIDENTIFIED; + } + + return requesterID; + } + + /** + * Signed Audit Log Serial Number + * + * This method is called to obtain the serial number of the certificate + * whose status is to be changed for a signed audit log message. + * <P> + * + * @param eeSerialNumber a string containing the un-normalized serialNumber + * @return id string containing the signed audit log message RequesterID + */ + private String auditSerialNumber(String eeSerialNumber) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String serialNumber = null; + + // Normalize the serialNumber + if (eeSerialNumber != null) { + serialNumber = eeSerialNumber.trim(); + + // convert it to hexadecimal + serialNumber = "0x" + (new BigInteger(serialNumber)).toString(16); + } else { + serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + return serialNumber; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java b/base/common/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java new file mode 100644 index 000000000..2a143b668 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java @@ -0,0 +1,184 @@ +// --- 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.cert; + +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.Locale; +import java.util.Random; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.cms.authentication.HashAuthentication; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * For Face-to-face enrollment, enable EE enrollment feature + * + * @version $Revision$, $Date$ + * @see com.netscape.cms.servlet.cert.DisableEnrollResult + */ +public class EnableEnrollResult extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -2646998784859783012L; + private final static String TPL_FILE = "enableEnrollResult.template"; + private String mFormPath = null; + private Random random = null; + + public EnableEnrollResult() { + super(); + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + // coming from agent + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + random = new Random(); + } + + protected CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Services the request + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "enable"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + X509Certificate sslClientCert = null; + + sslClientCert = getSSLClientCertificate(httpReq); + String dn = (String) sslClientCert.getSubjectDN().toString(); + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + if (!(mAuthority instanceof IRegistrationAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IConfigStore configStore = CMS.getConfigStore(); + String machine = configStore.getString("machineName"); + String port = CMS.getEESSLPort(); + + header.addStringValue("machineName", machine); + header.addStringValue("port", port); + String val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr; + + String host = args.getValueAsString("hostname", null); + boolean isEnable = mgr.isEnable(host); + + if (isEnable) { + header.addStringValue("code", "1"); + } else { + String timeout = args.getValueAsString("timeout", "600"); + + mgr.createEntry(host, dn, Long.parseLong(timeout) * 1000, + random.nextLong() + "", 0); + header.addStringValue("code", "0"); + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/EnrollServlet.java b/base/common/src/com/netscape/cms/servlet/cert/EnrollServlet.java new file mode 100644 index 000000000..a73a8146c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/EnrollServlet.java @@ -0,0 +1,1768 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.pkcs.PKCS10; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +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.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.KeyGenInfo; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertRecordList; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.IPolicyProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSGateway; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cms.servlet.processors.CMCProcessor; +import com.netscape.cms.servlet.processors.CRMFProcessor; +import com.netscape.cms.servlet.processors.KeyGenProcessor; +import com.netscape.cms.servlet.processors.PKCS10Processor; +import com.netscape.cms.servlet.processors.PKIProcessor; +import com.netscape.cmsutil.util.Utils; + +/** + * Submit a Certificate Enrollment request + * + * @version $Revision$, $Date$ + */ +public class EnrollServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -6983729702665630013L; + + public final static String ADMIN_ENROLL_SERVLET_ID = "caadminEnroll"; + + // enrollment templates. + public static final String ENROLL_SUCCESS_TEMPLATE = "EnrollSuccess.template"; + + // http params + public static final String OLD_CERT_TYPE = "csrCertType"; + public static final String CERT_TYPE = "certType"; + // same as in ConfigConstant.java + public static final String REQUEST_FORMAT = "reqFormat"; + public static final String REQUEST_FORMAT_PKCS10 = "PKCS10"; + public static final String REQUEST_FORMAT_CMC = "CMC"; + public static final String REQUEST_CONTENT = "requestContent"; + public static final String SUBJECT_KEYGEN_INFO = "subjectKeyGenInfo"; + public static final String PKCS10_REQUEST = "pkcs10Request"; + public static final String CMC_REQUEST = "cmcRequest"; + public static final String CRMF_REQUEST = "CRMFRequest"; + public static final String SUBJECT_NAME = "subject"; + public static final String CRMF_REQID = "crmfReqId"; + public static final String CHALLENGE_PASSWORD = "challengePhrase"; + + private static final String CERT_AUTH_DUAL = "dual"; + private static final String CERT_AUTH_ENCRYPTION = "encryption"; + private static final String CERT_AUTH_SINGLE = "single"; + private static final String CLIENT_ISSUER = "clientIssuer"; + + private boolean mAuthTokenOverride = true; + private String mEnrollSuccessTemplate = null; + private ICMSTemplateFiller mEnrollSuccessFiller = new ImportCertsTemplateFiller(); + + ICertificateAuthority mCa = null; + ICertificateRepository mRepository = null; + + private boolean enforcePop = false; + + private String auditServiceID = ILogger.UNIDENTIFIED; + private final static String ADMIN_CA_ENROLLMENT_SERVLET = + "caadminEnroll"; + private final static String AGENT_CA_BULK_ENROLLMENT_SERVLET = + "cabulkissuance"; + private final static String AGENT_RA_BULK_ENROLLMENT_SERVLET = + "rabulkissuance"; + private final static String EE_CA_CERT_BASED_ENROLLMENT_SERVLET = + "cacertbasedenrollment"; + private final static String EE_CA_ENROLLMENT_SERVLET = + "caenrollment"; + private final static String EE_RA_CERT_BASED_ENROLLMENT_SERVLET = + "racertbasedenrollment"; + private final static String EE_RA_ENROLLMENT_SERVLET = + "raenrollment"; + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + private final static String[] SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] { + + /* 0 */"automated non-profile cert request rejection: " + + "unable to render OLD_CERT_TYPE response", + + /* 1 */"automated non-profile cert request rejection: " + + "unable to complete handleEnrollAuditLog() method", + + /* 2 */"automated non-profile cert request rejection: " + + "unable to render success template", + + /* 3 */"automated non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException" + }; + private final static String LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST = + "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + private static final String HEADER = "-----BEGIN NEW CERTIFICATE REQUEST-----"; + private static final String TRAILER = "-----END NEW CERTIFICATE REQUEST-----"; + + public EnrollServlet() { + super(); + } + + /** + * initialize the servlet. + * <p> + * the following parameters are read from the servlet config: + * <ul> + * <li>CMSServlet.PROP_ID - ID for signed audit log messages + * <li>CMSServlet.PROP_SUCCESS_TEMPLATE - success template file + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + try { + super.init(sc); + + CMS.debug("EnrollServlet: In Enroll Servlet init!"); + + try { + IConfigStore configStore = CMS.getConfigStore(); + String PKI_Subsystem = configStore.getString("subsystem.0.id", + null); + + // CMS 6.1 began utilizing the "Certificate Profiles" framework + // instead of the legacy "Certificate Policies" framework. + // + // Beginning with CS 8.1, to meet the Common Criteria + // evaluation performed on this version of the product, it + // was determined that this legacy "Certificate Policies" + // framework would be deprecated and disabled by default + // (see Bugzilla Bug #472597). + // + // NOTE: The "Certificate Policies" framework ONLY applied to + // to CA, KRA, and legacy RA (pre-CMS 7.0) subsystems. + // + // Further, the "EnrollServlet.java" servlet is ONLY + // used by the CA for the following: + // + // SERVLET-NAME URL-PATTERN + // ==================================================== + // caadminEnroll ca/admin/ca/adminEnroll.html + // cabulkissuance ca/agent/ca/bulkissuance.html + // cacertbasedenrollment ca/certbasedenrollment.html + // caenrollment ca/enrollment.html + // + // The "EnrollServlet.java" servlet is NOT used by + // the KRA. + // + if (PKI_Subsystem.trim().equalsIgnoreCase("ca")) { + String policyStatus = PKI_Subsystem.trim().toLowerCase() + + "." + "Policy" + + "." + IPolicyProcessor.PROP_ENABLE; + + if (configStore.getBoolean(policyStatus, true) == true) { + // NOTE: If "<subsystem>.Policy.enable=<boolean>" + // is missing, then the referenced instance + // existed prior to this name=value pair + // existing in its 'CS.cfg' file, and thus + // we err on the side that the user may + // still need to use the policy framework. + CMS.debug("EnrollServlet::init Certificate " + + "Policy Framework (deprecated) " + + "is ENABLED"); + } else { + // CS 8.1 Default: <subsystem>.Policy.enable=false + CMS.debug("EnrollServlet::init Certificate " + + "Policy Framework (deprecated) " + + "is DISABLED"); + return; + } + } + } catch (EBaseException e) { + throw new ServletException("EnrollServlet::init - " + + "EBaseException: " + + "Unable to initialize " + + "Certificate Policy Framework " + + "(deprecated)"); + } + + // override success template to allow direct import of keygen certs. + mTemplates.remove(CMSRequest.SUCCESS); + + try { + // determine the service ID for signed audit log messages + String id = sc.getInitParameter(CMSServlet.PROP_ID); + + if (id != null) { + if (!(auditServiceID.equals( + ADMIN_CA_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + AGENT_CA_BULK_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + AGENT_RA_BULK_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + EE_CA_CERT_BASED_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + EE_CA_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + EE_RA_CERT_BASED_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + EE_RA_ENROLLMENT_SERVLET))) { + auditServiceID = ILogger.UNIDENTIFIED; + } else { + auditServiceID = id.trim(); + } + } + + mEnrollSuccessTemplate = sc.getInitParameter( + CMSServlet.PROP_SUCCESS_TEMPLATE); + if (mEnrollSuccessTemplate == null) + mEnrollSuccessTemplate = ENROLL_SUCCESS_TEMPLATE; + String fillername = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE_FILLER); + + if (fillername != null) { + ICMSTemplateFiller filler = newFillerObject(fillername); + + if (filler != null) + mEnrollSuccessFiller = filler; + } + + // cfu + mCa = (ICertificateAuthority) CMS.getSubsystem("ca"); + + init_testbed_hack(mConfig); + } catch (Exception e) { + // this should never happen. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", + e.toString(), mId)); + } + } catch (ServletException eAudit1) { + // rethrow caught exception + throw eAudit1; + } + } + + /** + * XXX (SHOULD CHANGE TO READ FROM Servletconfig) + * Getter method to see if Proof of Posession checking is enabled. + * this value is set in the CMS.cfg filem with the parameter + * "enrollment.enforcePop". It defaults to false + * + * @return true if user is required to Prove that they possess the + * private key corresponding to the public key in the certificate + * request they are submitting + */ + public boolean getEnforcePop() { + return enforcePop; + } + + /** + * Process the HTTP request. + * <UL> + * <LI>If the request is coming through the admin port, it is only allowed to continue if 'admin enrollment' is + * enabled in the CMS.cfg file + * <LI>If the CMS.cfg parameter useThreadNaming is true, the current thread is renamed with more information about + * the current request ID + * <LI>The request is preprocessed, then processed further in one of the cert request processor classes: + * KeyGenProcessor, PKCS10Processor, CMCProcessor, CRMFProcessor + * </UL> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + // SPECIAL CASE: + // if it is adminEnroll servlet,check if it's enabled + if (mId.equals(ADMIN_ENROLL_SERVLET_ID) && + !CMSGateway.getEnableAdminEnroll()) { + log(ILogger.LL_SECURITY, + CMS.getLogMessage("ADMIN_SRVLT_ENROLL_ACCESS_AFTER_SETUP")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REDIRECTING_ADMINENROLL_ERROR", + "Attempt to access adminEnroll after already setup.")); + } + + processX509(cmsReq); + } + + private boolean getCertAuthEnrollStatus(IArgBlock httpParams) { + + /* + * === certAuth based enroll === + * "certAuthEnroll" is on. + * "certauthEnrollType can be one of the three: + * single - it's for single cert enrollment + * dual - it's for dual certs enrollment + * encryption - getting the encryption cert only via + * authentication of the signing cert + * (crmf or keyGenInfo) + */ + boolean certAuthEnroll = false; + + String certAuthEnrollOn = + httpParams.getValueAsString("certauthEnroll", null); + + if ((certAuthEnrollOn != null) && (certAuthEnrollOn.equals("on"))) { + certAuthEnroll = true; + CMS.debug("EnrollServlet: certAuthEnroll is on"); + } + + return certAuthEnroll; + + } + + private String getCertAuthEnrollType(IArgBlock httpParams, boolean certAuthEnroll) + throws EBaseException { + + String certauthEnrollType = null; + + if (certAuthEnroll == true) { + certauthEnrollType = + httpParams.getValueAsString("certauthEnrollType", null); + if (certauthEnrollType != null) { + if (certauthEnrollType.equals("dual")) { + CMS.debug("EnrollServlet: certauthEnrollType is dual"); + } else if (certauthEnrollType.equals("encryption")) { + CMS.debug("EnrollServlet: certauthEnrollType is encryption"); + } else if (certauthEnrollType.equals("single")) { + CMS.debug("EnrollServlet: certauthEnrollType is single"); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_CERTAUTH_ENROLL_TYPE_1", certauthEnrollType)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERTAUTH_ENROLL_TYPE")); + } + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("MSGW_MISSING_CERTAUTH_ENROLL_TYPE")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CERTAUTH_ENROLL_TYPE")); + } + } + + return certauthEnrollType; + + } + + private boolean checkClientCertSigningOnly(X509Certificate sslClientCert) + throws EBaseException { + if ((CMS.isSigningCert((X509CertImpl) sslClientCert) == + false) || + ((CMS.isSigningCert((X509CertImpl) sslClientCert) == + true) && + (CMS.isEncryptionCert((X509CertImpl) sslClientCert) == + true))) { + + // either it's not a signing cert, or it's a dual cert + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_CERT_TYPE")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERT_TYPE")); + } + + return true; + } + + private X509CertInfo[] handleCertAuthDual(X509CertInfo certInfo, IAuthToken authToken, + X509Certificate sslClientCert, + ICertificateAuthority mCa, String certBasedOldSubjectDN, + BigInteger certBasedOldSerialNum) + throws EBaseException { + + CMS.debug("EnrollServlet: In handleCertAuthDual!"); + + if (mCa == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NOT_A_CA")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_A_CA")); + } + + // first, make sure the client cert is indeed a + // signing only cert + + try { + + checkClientCertSigningOnly(sslClientCert); + } catch (ECMSGWException e) { + + throw new ECMSGWException(e.toString()); + + } + + X509Key key = null; + + // for signing cert + key = (X509Key) sslClientCert.getPublicKey(); + try { + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_IO", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } + + String filter = + "(&(x509cert.subject=" + + certBasedOldSubjectDN + ")(!(x509cert.serialNumber=" + certBasedOldSerialNum + + "))(certStatus=VALID))"; + ICertRecordList list = + (ICertRecordList) mCa.getCertificateRepository().findCertRecordsInList(filter, null, 10); + int size = list.getSize(); + Enumeration<ICertRecord> en = list.getCertRecords(0, size - 1); + + CMS.debug("EnrollServlet: signing cert filter " + filter); + + if (!en.hasMoreElements()) { + CMS.debug("EnrollServlet: pairing encryption cert not found!"); + return null; + // pairing encryption cert not found + } else { + X509CertInfo encCertInfo = CMS.getDefaultX509CertInfo(); + X509CertInfo[] cInfoArray = new X509CertInfo[] { certInfo, + encCertInfo }; + int i = 1; + + boolean encCertFound = false; + + while (en.hasMoreElements()) { + ICertRecord record = en.nextElement(); + X509CertImpl cert = record.getCertificate(); + + // if not encryption cert only, try next one + if ((CMS.isEncryptionCert(cert) == false) || + ((CMS.isEncryptionCert(cert) == true) && + (CMS.isSigningCert(cert) == true))) { + + CMS.debug("EnrollServlet: Not encryption only cert, will try next one."); + continue; + } + + key = (X509Key) cert.getPublicKey(); + CMS.debug("EnrollServlet: Found key for encryption cert."); + encCertFound = true; + + try { + encCertInfo = (X509CertInfo) + cert.get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + + } catch (CertificateParsingException ex) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTINFO_ENCRYPT_CERT")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CERTINFO")); + } + + try { + encCertInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } + + CMS.debug("EnrollServlet: About to fillCertInfoFromAuthToken!"); + PKIProcessor.fillCertInfoFromAuthToken(encCertInfo, authToken); + + cInfoArray[i++] = encCertInfo; + break; + + } + if (encCertFound == false) { + CMS.debug("EnrollServlet: Leaving because Enc Cert not found."); + return null; + } + + CMS.debug("EnrollServlet: returning cInfoArray of length " + cInfoArray.length); + return cInfoArray; + } + + } + + private boolean handleEnrollAuditLog(IRequest req, CMSRequest cmsReq, String authMgr, IAuthToken authToken, + X509CertInfo certInfo, long startTime) + throws EBaseException { + //for audit log + + String initiative = null; + String agentID = null; + + if (authToken == null) { + // request is from eegateway, so fromUser. + initiative = AuditFormat.FROMUSER; + } else { + agentID = authToken.getInString("userid"); + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID; + } + + // if service not complete return standard templates. + RequestStatus status = req.getRequestStatus(); + + if (status != RequestStatus.COMPLETE) { + cmsReq.setIRequestStatus(); // set status acc. to IRequest status. + // audit log the status + try { + if (status == RequestStatus.REJECTED) { + Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration<String> msgs = messages.elements(); + StringBuffer wholeMsg = new StringBuffer(); + + while (msgs.hasMoreElements()) { + wholeMsg.append("\n"); + wholeMsg.append(msgs.nextElement()); + } + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + certInfo.get(X509CertInfo.SUBJECT), + " violation: " + + wholeMsg.toString() } + ); + } else { // no policy violation, from agent + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + certInfo.get(X509CertInfo.SUBJECT), "" } + ); + } + } else { // other imcomplete status + long endTime = CMS.getCurrentDate().getTime(); + + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + certInfo.get(X509CertInfo.SUBJECT) + " time: " + (endTime - startTime), "" } + ); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", + e.toString())); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", + e.toString())); + } + return false; + } + // if service error use standard error templates. + Integer result = req.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(req.getExtDataInString(IRequest.ERROR)); + String[] svcErrors = + req.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + //System.out.println( + //"revocation servlet: setting error description "+ + //err.toString()); + cmsReq.setErrorDescription(err); + // audit log the error + try { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + "completed with error: " + + err, + certInfo.get(X509CertInfo.SUBJECT), "" + } + ); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", + e.toString())); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", + e.toString())); + } + + } + } + } + return false; + + } + + return true; + + } + + /** + * Process X509 certificate enrollment request + * <P> + * + * (Certificate Request - either an "admin" cert request for an admin certificate, an "agent" cert request for + * "bulk enrollment", or an "EE" standard cert request) + * <P> + * + * (Certificate Request Processed - either an automated "admin" non-profile based CA admin cert acceptance, an + * automated "admin" non-profile based CA admin cert rejection, an automated "EE" non-profile based cert acceptance, + * or an automated "EE" non-profile based cert rejection) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST used when a non-profile cert request is made + * (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @param cmsReq a certificate enrollment request + * @exception EBaseException an error has occurred + */ + protected void processX509(CMSRequest cmsReq) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = ILogger.UNIDENTIFIED; + String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String id = null; + + // define variables common to try-catch-blocks + long startTime = 0; + IArgBlock httpParams = null; + HttpServletRequest httpReq = null; + IAuthToken authToken = null; + AuthzToken authzToken = null; + IRequest req = null; + X509CertInfo certInfo = null; + + IConfigStore configStore = CMS.getConfigStore(); + + /* XXX shouldn't we read this from ServletConfig at init time? */ + enforcePop = configStore.getBoolean("enrollment.enforcePop", false); + CMS.debug("EnrollServlet: enforcePop " + enforcePop); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + startTime = CMS.getCurrentDate().getTime(); + httpParams = cmsReq.getHttpParams(); + httpReq = cmsReq.getHttpReq(); + if (mAuthMgr != null) { + authToken = authenticate(cmsReq); + } + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "submit"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + return; + } + + // create enrollment request in request queue. + req = mRequestQueue.newRequest(IRequest.ENROLLMENT_REQUEST); + + // retrieve the actual "auditRequesterID" + if (req != null) { + // overwrite "auditRequesterID" if and only if "id" != null + id = req.getRequestId().toString(); + if (id != null) { + auditRequesterID = id.trim(); + } + } + + try { + if (CMS.getConfigStore().getBoolean("useThreadNaming", false)) { + String currentName = Thread.currentThread().getName(); + + Thread.currentThread().setName(currentName + + "-request-" + + req.getRequestId().toString() + + "-" + + (new Date()).getTime()); + } + } catch (Exception e) { + } + + /* + * === certAuth based enroll === + * "certAuthEnroll" is on. + * "certauthEnrollType can be one of the three: + * single - it's for single cert enrollment + * dual - it's for dual certs enrollment + * encryption - getting the encryption cert only via + * authentication of the signing cert + * (crmf or keyGenInfo) + */ + boolean certAuthEnroll = false; + String certauthEnrollType = null; + + certAuthEnroll = getCertAuthEnrollStatus(httpParams); + + try { + if (certAuthEnroll == true) { + certauthEnrollType = getCertAuthEnrollType(httpParams, + certAuthEnroll); + } + } catch (ECMSGWException e) { + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException(e.toString()); + } + + CMS.debug("EnrollServlet: In EnrollServlet.processX509!"); + CMS.debug("EnrollServlet: certAuthEnroll " + certAuthEnroll); + CMS.debug("EnrollServlet: certauthEnrollType " + certauthEnrollType); + + String challengePassword = httpParams.getValueAsString( + "challengePassword", ""); + + cmsReq.setIRequest(req); + saveHttpHeaders(httpReq, req); + saveHttpParams(httpParams, req); + + X509Certificate sslClientCert = null; + + // cert auth enroll + String certBasedOldSubjectDN = null; + BigInteger certBasedOldSerialNum = null; + + // check if request was authenticated, if so set authtoken & + // certInfo. also if authenticated, take certInfo from authToken. + certInfo = null; + if (certAuthEnroll == true) { + sslClientCert = getSSLClientCertificate(httpReq); + if (sslClientCert == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SSL_CLIENT_CERT")); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SSL_CLIENT_CERT")); + } + + certBasedOldSubjectDN = (String) + sslClientCert.getSubjectDN().toString(); + certBasedOldSerialNum = (BigInteger) + sslClientCert.getSerialNumber(); + + CMS.debug("EnrollServlet: certBasedOldSubjectDN " + certBasedOldSubjectDN); + CMS.debug("EnrollServlet: certBasedOldSerialNum " + certBasedOldSerialNum); + + // if the cert subject name is NOT MISSING, retrieve the + // actual "auditCertificateSubjectName" and "normalize" it + if (certBasedOldSubjectDN != null) { + // NOTE: This is ok even if the cert subject name + // is "" (empty)! + auditCertificateSubjectName = certBasedOldSubjectDN.trim(); + } + + try { + certInfo = (X509CertInfo) + ((X509CertImpl) sslClientCert).get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + } catch (CertificateParsingException ex) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTINFO")); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_CERTINFO")); + } + } else { + CMS.debug("EnrollServlet: No CertAuthEnroll."); + certInfo = CMS.getDefaultX509CertInfo(); + } + + X509CertInfo[] certInfoArray = new X509CertInfo[] { certInfo }; + + String authMgr = AuditFormat.NOAUTH; + + // if authentication + if (authToken != null) { + authMgr = + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + // don't store agent token in request. + // agent currently used for bulk issuance. + // if (!authMgr.equals(AuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + log(ILogger.LL_INFO, + "Enrollment request was authenticated by " + + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME)); + + PKIProcessor.fillCertInfoFromAuthToken(certInfo, + authToken); + // save authtoken attrs to request directly + // (for policy use) + saveAuthToken(authToken, req); + // req.set(IRequest.AUTH_TOKEN, authToken); + // } + } + + CMS.debug("EnrollServlet: Enroll authMgr " + authMgr); + + if (certAuthEnroll == true) { + // log(ILogger.LL_DEBUG, + // "just gotten subjectDN and serialNumber " + + // "from ssl client cert"); + if (authToken == null) { + // authToken is null, can't match to anyone; bail! + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_PROCESS_ENROLL_NO_AUTH")); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + return; + } + } + + // fill certInfo from input types: keygen, cmc, pkcs10 or crmf + KeyGenInfo keyGenInfo = httpParams.getValueAsKeyGenInfo( + SUBJECT_KEYGEN_INFO, null); + PKCS10 pkcs10 = null; + + // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType + // instead of certType + String certType = httpParams.getValueAsString(OLD_CERT_TYPE, null); + CMS.debug("EnrollServlet: certType " + certType); + + if (certType == null) { + certType = httpParams.getValueAsString(CERT_TYPE, "client"); + CMS.debug("EnrollServlet: certType " + certType); + } else { + // some policies may rely on the fact that + // CERT_TYPE is set. So for 3.5.1 or eariler + // we need to set CERT_TYPE here. + req.setExtData(IRequest.HTTP_PARAMS, CERT_TYPE, certType); + } + if (certType.equals("client")) { + // coming from MSIE + String p10b64 = httpParams.getValueAsString(PKCS10_REQUEST, + null); + + if (p10b64 != null) { + try { + byte[] bytes = CMS.AtoB(p10b64); + + pkcs10 = new PKCS10(bytes); + } catch (Exception e) { + // ok, if the above fails, it could + // be a PKCS10 with header + pkcs10 = httpParams.getValueAsPKCS10(PKCS10_REQUEST, + false, null); + // e.printStackTrace(); + } + } + + //pkcs10 = httpParams.getValuePKCS10(PKCS10_REQUEST, null); + + } else { + try { + // coming from server cut & paste blob. + pkcs10 = httpParams.getValueAsPKCS10(PKCS10_REQUEST, + false, null); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + String cmc = null; + String asciiBASE64Blob = httpParams.getValueAsString(CMC_REQUEST, null); + + if (asciiBASE64Blob != null) { + int startIndex = asciiBASE64Blob.indexOf(HEADER); + int endIndex = asciiBASE64Blob.indexOf(TRAILER); + if (startIndex != -1 && endIndex != -1) { + startIndex = startIndex + HEADER.length(); + cmc = asciiBASE64Blob.substring(startIndex, endIndex); + } else + cmc = asciiBASE64Blob; + CMS.debug("EnrollServlet: cmc " + cmc); + } + + String crmf = httpParams.getValueAsString(CRMF_REQUEST, null); + + CMS.debug("EnrollServlet: crmf " + crmf); + + if (certAuthEnroll == true) { + + PKIProcessor.fillCertInfoFromAuthToken(certInfo, authToken); + + // for dual certs + if (certauthEnrollType.equals(CERT_AUTH_DUAL)) { + + CMS.debug("EnrollServlet: Attempting CERT_AUTH_DUAL"); + boolean gotEncCert = false; + X509CertInfo[] cInfoArray = null; + + try { + cInfoArray = handleCertAuthDual(certInfo, authToken, + sslClientCert, mCa, + certBasedOldSubjectDN, + certBasedOldSerialNum); + } catch (ECMSGWException e) { + // store a message in the signed audit log file + // (either an "admin" cert request for an admin + // certificate, an "agent" cert request for + // "bulk enrollment", or an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException(e.toString()); + } + + if (cInfoArray != null && cInfoArray.length != 0) { + CMS.debug("EnrollServlet: cInfoArray Length " + cInfoArray.length); + + certInfoArray = cInfoArray; + gotEncCert = true; + } + + if (gotEncCert == false) { + // encryption cert not found, bail + log(ILogger.LL_FAILURE, + CMS.getLogMessage( + "CMSGW_ENCRYPTION_CERT_NOT_FOUND")); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin + // certificate, an "agent" cert request for + // "bulk enrollment", or an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCRYPTION_CERT_NOT_FOUND")); + } + + } else if (certauthEnrollType.equals(CERT_AUTH_ENCRYPTION)) { + + // first, make sure the client cert is indeed a + // signing only cert + + try { + + checkClientCertSigningOnly(sslClientCert); + } catch (ECMSGWException e) { + // store a message in the signed audit log file + // (either an "admin" cert request for an admin + // certificate, an "agent" cert request for + // "bulk enrollment", or an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException(e.toString()); + } + + /* + * either crmf or keyGenInfo + */ + if (keyGenInfo != null) { + KeyGenProcessor keyGenProc = new KeyGenProcessor(cmsReq, + this); + + keyGenProc.fillCertInfo(null, certInfo, + authToken, httpParams); + + req.setExtData(CLIENT_ISSUER, + sslClientCert.getIssuerDN().toString()); + CMS.debug("EnrollServlet: sslClientCert issuerDN = " + + sslClientCert.getIssuerDN().toString()); + } else if (crmf != null && crmf != "") { + CRMFProcessor crmfProc = new CRMFProcessor(cmsReq, this, enforcePop); + + certInfoArray = crmfProc.fillCertInfoArray(crmf, + authToken, + httpParams, + req); + + req.setExtData(CLIENT_ISSUER, + sslClientCert.getIssuerDN().toString()); + CMS.debug("EnrollServlet: sslClientCert issuerDN = " + + sslClientCert.getIssuerDN().toString()); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_PROCESS_ENROLL_REQ") + + CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO")); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin + // certificate, an "agent" cert request for + // "bulk enrollment", or an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_KEYGEN_INFO")); + } + + } else if (certauthEnrollType.equals(CERT_AUTH_SINGLE)) { + + // have to be buried here to handle the issuer + + if (keyGenInfo != null) { + KeyGenProcessor keyGenProc = new KeyGenProcessor(cmsReq, + this); + + keyGenProc.fillCertInfo(null, certInfo, + authToken, httpParams); + } else if (pkcs10 != null) { + PKCS10Processor pkcs10Proc = new PKCS10Processor(cmsReq, + this); + + pkcs10Proc.fillCertInfo(pkcs10, certInfo, + authToken, httpParams); + } else if (cmc != null && cmc != "") { + CMCProcessor cmcProc = new CMCProcessor(cmsReq, this, enforcePop); + + certInfoArray = cmcProc.fillCertInfoArray(cmc, + authToken, + httpParams, + req); + } else if (crmf != null && crmf != "") { + CRMFProcessor crmfProc = new CRMFProcessor(cmsReq, this, enforcePop); + + certInfoArray = crmfProc.fillCertInfoArray(crmf, + authToken, + httpParams, + req); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_PROCESS_ENROLL_REQ") + + CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO")); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin + // certificate, an "agent" cert request for + // "bulk enrollment", or an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_KEYGEN_INFO")); + } + req.setExtData(CLIENT_ISSUER, + sslClientCert.getIssuerDN().toString()); + } + + } else if (keyGenInfo != null) { + + CMS.debug("EnrollServlet: Trying KeyGen with no cert auth."); + KeyGenProcessor keyGenProc = new KeyGenProcessor(cmsReq, this); + + keyGenProc.fillCertInfo(null, certInfo, authToken, httpParams); + } else if (pkcs10 != null) { + CMS.debug("EnrollServlet: Trying PKCS10 with no cert auth."); + PKCS10Processor pkcs10Proc = new PKCS10Processor(cmsReq, this); + + pkcs10Proc.fillCertInfo(pkcs10, certInfo, authToken, httpParams); + } else if (cmc != null) { + CMS.debug("EnrollServlet: Trying CMC with no cert auth."); + CMCProcessor cmcProc = new CMCProcessor(cmsReq, this, enforcePop); + + certInfoArray = cmcProc.fillCertInfoArray(cmc, authToken, + httpParams, req); + } else if (crmf != null && crmf != "") { + CMS.debug("EnrollServlet: Trying CRMF with no cert auth."); + CRMFProcessor crmfProc = new CRMFProcessor(cmsReq, this, enforcePop); + + certInfoArray = crmfProc.fillCertInfoArray(crmf, authToken, + httpParams, req); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_PROCESS_ENROLL_REQ") + + CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO")); + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_KEYGEN_INFO")); + } + + // if ca, fill in default signing alg here + + try { + ICertificateAuthority caSub = + (ICertificateAuthority) CMS.getSubsystem("ca"); + if (certInfoArray != null && caSub != null) { + for (int ix = 0; ix < certInfoArray.length; ix++) { + X509CertInfo ci = (X509CertInfo) certInfoArray[ix]; + String defaultSig = caSub.getDefaultAlgorithm(); + AlgorithmId algid = AlgorithmId.get(defaultSig); + ci.set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId(algid)); + } + } + } catch (Exception e) { + CMS.debug("Failed to set signing alg to certinfo " + e.toString()); + } + + req.setExtData(IRequest.CERT_INFO, certInfoArray); + + if (challengePassword != null && !challengePassword.equals("")) { + String pwd = hashPassword(challengePassword); + + req.setExtData(CHALLENGE_PASSWORD, pwd); + } + + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + // (either an "admin" cert request for an admin certificate, + // an "agent" cert request for "bulk enrollment", or + // an "EE" standard cert request) + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + + throw eAudit1; + } + + X509CertImpl[] issuedCerts = null; + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + // send request to request queue. + mRequestQueue.processRequest(req); + // process result. + + // render OLD_CERT_TYPE's response differently, we + // do not want any javascript in HTML, and need to + // override the default render. + if (httpParams.getValueAsString(OLD_CERT_TYPE, null) != null) { + try { + renderServerEnrollResult(cmsReq); + cmsReq.setStatus(CMSRequest.SUCCESS); // no default render + + issuedCerts = + cmsReq.getIRequest().getExtDataInCertArray( + IRequest.ISSUED_CERTS); + + for (int i = 0; i < issuedCerts.length; i++) { + // (automated "agent" cert request processed + // - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue(issuedCerts[i])); + + audit(auditMessage); + } + } catch (IOException ex) { + cmsReq.setStatus(CMSRequest.ERROR); + + // (automated "agent" 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); + } + + return; + } + + boolean completed = handleEnrollAuditLog(req, cmsReq, + mAuthMgr, authToken, + certInfo, startTime); + + if (completed == false) { + // (automated "agent" 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[1]); + + audit(auditMessage); + + return; + } + + // service success + cmsReq.setStatus(CMSRequest.SUCCESS); + issuedCerts = req.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + String initiative = null; + String agentID; + + if (authToken == null) { + // request is from eegateway, so fromUser. + initiative = AuditFormat.FROMUSER; + } else { + agentID = authToken.getInString("userid"); + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID; + } + + // audit log the success. + long endTime = CMS.getCurrentDate().getTime(); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] + { req.getRequestId(), + initiative, + mAuthMgr, + "completed", + issuedCerts[0].getSubjectDN(), + "cert issued serial number: 0x" + + issuedCerts[0].getSerialNumber().toString(16) + + " time: " + + (endTime - startTime) } + ); + + // handle initial admin enrollment if in adminEnroll mode. + checkAdminEnroll(cmsReq, issuedCerts); + + // return cert as mime type binary if requested. + if (checkImportCertToNav(cmsReq.getHttpResp(), + httpParams, issuedCerts[0])) { + cmsReq.setStatus(CMSRequest.SUCCESS); + + for (int i = 0; i < issuedCerts.length; i++) { + // (automated "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue(issuedCerts[i])); + + audit(auditMessage); + } + + return; + } + + // use success template. + try { + cmsReq.setResult(issuedCerts); + renderTemplate(cmsReq, mEnrollSuccessTemplate, + mEnrollSuccessFiller); + cmsReq.setStatus(CMSRequest.SUCCESS); + + for (int i = 0; i < issuedCerts.length; i++) { + // (automated "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue(issuedCerts[i])); + + audit(auditMessage); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_TEMP_REND_ERR", + mEnrollSuccessFiller.toString(), + e.toString())); + + // (automated "agent" 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[2]); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_RETURNING_RESULT_ERROR")); + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + // (automated "agent" 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[3]); + + audit(auditMessage); + + throw eAudit1; + } + + return; + } + + /** + * check if this is first enroll from admin enroll. + * If so disable admin enroll from here on. + */ + protected void checkAdminEnroll(CMSRequest cmsReq, X509CertImpl[] issuedCerts) + throws EBaseException { + // this is special case, get the admin certificate + if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID)) { + addAdminAgent(cmsReq, issuedCerts); + CMSGateway.disableAdminEnroll(); + } + } + + protected void addAdminAgent(CMSRequest cmsReq, X509CertImpl[] issuedCerts) + throws EBaseException { + String userid = cmsReq.getHttpParams().getValueAsString("uid"); + IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + + IUser adminuser = ug.createUser(userid); + + adminuser.setX509Certificates(issuedCerts); + try { + ug.addUserCert(adminuser); + } catch (netscape.ldap.LDAPException e) { + CMS.debug( + "EnrollServlet: Cannot add admin's certificate to its entry in the " + + "user group database. Error " + e); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ADDING_ADMIN_CERT_ERROR", e.toString())); + } + IGroup agentGroup = + ug.getGroupFromName(CA_AGENT_GROUP); + + if (agentGroup != null) { + // add user to the group if necessary + if (!agentGroup.isMember(userid)) { + agentGroup.addMemberName(userid); + ug.modifyGroup(agentGroup); + mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP, + AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT, + new Object[] { userid, userid, CA_AGENT_GROUP } + ); + + } + } else { + String msg = "Cannot add admin to the " + + CA_AGENT_GROUP + + " group: Group does not exist."; + + CMS.debug("EnrollServlet: " + msg); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_ADMIN_ERROR")); + } + } + + protected void renderServerEnrollResult(CMSRequest cmsReq) throws + IOException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + httpResp.setContentType("text/html"); + ServletOutputStream out = null; + + out = httpResp.getOutputStream(); + + // get template based on request status + out.println("<HTML>"); + out.println("<TITLE>"); + out.println("Server Enrollment"); + out.println("</TITLE>"); + // out.println("<BODY BGCOLOR=white>"); + + if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.COMPLETE)) { + out.println("<H1>"); + out.println("SUCCESS"); + out.println("</H1>"); + out.println("Your request is submitted and approved. Please cut and paste the certificate into your server."); // XXX - localize the message + out.println("<P>"); + out.println("Request Creation Time: "); + out.println(cmsReq.getIRequest().getCreationTime().toString()); + out.println("<P>"); + out.println("Request Status: "); + out.println(cmsReq.getStatus().toString()); + out.println("<P>"); + out.println("Request ID: "); + out.println(cmsReq.getIRequest().getRequestId().toString()); + out.println("<P>"); + out.println("Certificate: "); + out.println("<P>"); + out.println("<PRE>"); + X509CertImpl certs[] = + cmsReq.getIRequest().getExtDataInCertArray(IRequest.ISSUED_CERTS); + + out.println(CMS.getEncodedCert(certs[0])); + out.println("</PRE>"); + out.println("<P>"); + out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" + + cmsReq.getIRequest().getCreationTime().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_STATUS=" + + cmsReq.getStatus().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_ID=" + + cmsReq.getIRequest().getRequestId().toString() + ">"); + out.println("<!HTTP_OUTPUT X509_CERTIFICATE=" + + CMS.getEncodedCert(certs[0]) + ">"); + } else if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.PENDING)) { + out.println("<H1>"); + out.println("PENDING"); + out.println("</H1>"); + out.println("Your request is submitted. You can check on the status of your request with an authorized agent or local administrator by referring to the request ID."); // XXX - localize the message + out.println("<P>"); + out.println("Request Creation Time: "); + out.println(cmsReq.getIRequest().getCreationTime().toString()); + out.println("<P>"); + out.println("Request Status: "); + out.println(cmsReq.getStatus().toString()); + out.println("<P>"); + out.println("Request ID: "); + out.println(cmsReq.getIRequest().getRequestId().toString()); + out.println("<P>"); + out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" + + cmsReq.getIRequest().getCreationTime().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_STATUS=" + + cmsReq.getStatus().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_ID=" + + cmsReq.getIRequest().getRequestId().toString() + ">"); + } else { + out.println("<H1>"); + out.println("ERROR"); + out.println("</H1>"); + out.println("<!INFO>"); + out.println("Please consult your local administrator for assistance."); // XXX - localize the message + out.println("<!/INFO>"); + out.println("<P>"); + out.println("Request Status: "); + out.println(cmsReq.getStatus().toString()); + out.println("<P>"); + out.println("Error: "); + out.println(cmsReq.getError()); // XXX - need to parse in Locale + out.println("<P>"); + out.println("<!HTTP_OUTPUT REQUEST_STATUS=" + + cmsReq.getStatus().toString() + ">"); + out.println("<!HTTP_OUTPUT ERROR=" + + cmsReq.getError() + ">"); + } + + /** + * // include all the input data + * ArgBlock args = cmsReq.getHttpParams(); + * Enumeration ele = args.getElements(); + * while (ele.hasMoreElements()) { + * String eleT = (String)ele.nextElement(); + * out.println("<!HTTP_INPUT " + eleT + "=" + + * args.get(eleT) + ">"); + * } + **/ + + out.println("</HTML>"); + } + + // XXX ALERT !! + // Remove the following and calls to them when we bundle a cartman + // later than alpha1. + // These are here to cover up problem in cartman where the + // key usage extension always ends up being digital signature only + // and for rsa-ex ends up having no bits set. + + private boolean mIsTestBed = false; + + private void init_testbed_hack(IConfigStore config) + throws EBaseException { + mIsTestBed = config.getBoolean("isTestBed", true); + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param 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 = Utils.base64encode(rawData).trim(); + + StringBuffer sb = new StringBuffer(); + // extract all line separators from the "base64Data" + for (int i = 0; i < base64Data.length(); i++) { + if (base64Data.substring(i, i).getBytes() != EOL) { + sb.append(base64Data.substring(i, i)); + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/GetBySerial.java b/base/common/src/com/netscape/cms/servlet/cert/GetBySerial.java new file mode 100644 index 000000000..663397f54 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/GetBySerial.java @@ -0,0 +1,296 @@ +// --- 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.cert; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.pkcs.ContentInfo; +import netscape.security.pkcs.PKCS7; +import netscape.security.pkcs.SignerInfo; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.X509CertImpl; + +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.base.IArgBlock; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.crypto.CryptoUtil; + +/** + * Retrieve certificate by serial number. + * + * @version $Revision$, $Date$ + */ +public class GetBySerial extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -2276677839178370838L; + + private final static String INFO = "GetBySerial"; + + private final static String IMPORT_CERT_TEMPLATE = "ImportCert.template"; + private String mImportTemplate = null; + private String mIETemplate = null; + private ICMSTemplateFiller mImportTemplateFiller = null; + IRequestQueue mReqQ = null; + + public GetBySerial() { + super(); + } + + /** + * Initialize the servlet. This servlet uses the template file + * "ImportCert.template" to import the cert to the users browser, + * if that is what the user requested + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + try { + mImportTemplate = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE); + mIETemplate = sc.getInitParameter("importCertTemplate"); + if (mImportTemplate == null) + mImportTemplate = IMPORT_CERT_TEMPLATE; + } catch (Exception e) { + mImportTemplate = null; + } + mImportTemplateFiller = new ImportCertsTemplateFiller(); + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + + ICertificateAuthority mCa = (ICertificateAuthority) CMS.getSubsystem("ca"); + if (mCa == null) { + return; + } + + mReqQ = mCa.getRequestQueue(); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param serialNumber serial number of certificate in HEX + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + IArgBlock args = cmsReq.getHttpParams(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "import"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String serial = args.getValueAsString("serialNumber", null); + String browser = args.getValueAsString("browser", null); + BigInteger serialNo = null; + + try { + serialNo = new BigInteger(serial, 16); + } catch (NumberFormatException e) { + serialNo = null; + } + if (serial == null || serialNo == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_SERIAL_NUMBER")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_SERIAL_NUMBER"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + ICertRecord certRecord = (ICertRecord) getCertRecord(serialNo); + if (certRecord == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CERT_SERIAL_NOT_FOUND_1", serialNo.toString(16))); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_CERT_SERIAL_NOT_FOUND", "0x" + serialNo.toString(16)))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + // if RA, needs requestOwner to match + // first, find the user's group + if (authToken != null) { + String group = authToken.getInString("group"); + + if ((group != null) && (group != "")) { + CMS.debug("GetBySerial process: auth group=" + group); + if (group.equals("Registration Manager Agents")) { + boolean groupMatched = false; + // find the cert record's orig. requestor's group + MetaInfo metai = certRecord.getMetaInfo(); + if (metai != null) { + String reqId = (String) metai.get(ICertRecord.META_REQUEST_ID); + RequestId rid = new RequestId(reqId); + IRequest creq = mReqQ.findRequest(rid); + if (creq != null) { + String reqOwner = creq.getRequestOwner(); + if (reqOwner != null) { + CMS.debug("GetBySerial process: req owner=" + reqOwner); + if (reqOwner.equals(group)) + groupMatched = true; + } + } + } + if (groupMatched == false) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CERT_SERIAL_NOT_FOUND_1", serialNo.toString(16))); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_CERT_SERIAL_NOT_FOUND", "0x" + serialNo.toString(16)))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + } + } + } + + X509CertImpl cert = certRecord.getCertificate(); + + if (cert != null) { + // if there's a crmf request id, set that too. + if (browser != null && browser.equals("ie")) { + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + Locale[] locale = new Locale[1]; + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + CertificateChain cachain = ca.getCACertChain(); + X509Certificate[] cacerts = cachain.getChain(); + X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1]; + int m = 1, n = 0; + + for (; n < cacerts.length; m++, n++) { + userChain[m] = (X509CertImpl) cacerts[n]; + } + + userChain[0] = cert; + PKCS7 p7 = new PKCS7(new AlgorithmId[0], + new ContentInfo(new byte[0]), userChain, new SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + try { + p7.encodeSignedData(bos); + } catch (Exception eee) { + } + + byte[] p7Bytes = bos.toByteArray(); + String p7Str = CMS.BtoA(p7Bytes); + + header.addStringValue("pkcs7", CryptoUtil.normalizeCertStr(p7Str)); + try { + CMSTemplate form = getTemplate(mIETemplate, req, locale); + ServletOutputStream out = response.getOutputStream(); + cmsReq.setStatus(CMSRequest.SUCCESS); + response.setContentType("text/html"); + form.renderOutput(out, argSet); + return; + } catch (Exception ee) { + CMS.debug("GetBySerial process: Exception=" + ee.toString()); + } + } //browser is IE + + MetaInfo metai = certRecord.getMetaInfo(); + String crmfReqId = null; + + if (metai != null) { + crmfReqId = (String) metai.get(ICertRecord.META_CRMF_REQID); + if (crmfReqId != null) + cmsReq.setResult(IRequest.CRMF_REQID, crmfReqId); + } + + if (crmfReqId == null && checkImportCertToNav( + cmsReq.getHttpResp(), cmsReq.getHttpParams(), cert)) { + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + // use import cert template to return cert. + X509CertImpl[] certs = new X509CertImpl[] { (X509CertImpl) cert }; + + cmsReq.setResult(certs); + + cmsReq.setStatus(CMSRequest.SUCCESS); + + // XXX follow request in cert record to set certtype, which will + // import cert only if it's client. For now assume "client" if + // someone clicked to import this cert. + cmsReq.getHttpParams().set("certType", "client"); + + try { + renderTemplate(cmsReq, mImportTemplate, mImportTemplateFiller); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/GetCAChain.java b/base/common/src/com/netscape/cms/servlet/cert/GetCAChain.java new file mode 100644 index 000000000..fe55f335b --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/GetCAChain.java @@ -0,0 +1,407 @@ +// --- 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.cert; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CertificateChain; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.ICertPrettyPrint; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve the Certificates comprising the CA Chain for this CA. + * + * @version $Revision$, $Date$ + */ +public class GetCAChain extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -8189048155415074581L; + private final static String TPL_FILE = "displayCaCert.template"; + private String mFormPath = null; + + public GetCAChain() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + // override success to display own output. + mTemplates.remove(CMSRequest.SUCCESS); + // coming from ee + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param op 'downloadBIN' - return the binary certificate chain + * <li>http.param op 'displayIND' - display pretty-print of certificate chain components + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + // Get the operation code + String op = null; + + op = args.getValueAsString("op", null); + if (op == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_OPTIONS_SELECTED")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_OPTIONS_SELECTED")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + + AuthzToken authzToken = null; + + if (op.startsWith("download")) { + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "download"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + downloadChain(op, args, httpReq, httpResp, cmsReq); + } else if (op.startsWith("display")) { + try { + authzToken = mAuthz.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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + displayChain(op, args, httpReq, httpResp, cmsReq); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_OPTIONS_CA_CHAIN")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_OPTIONS_SELECTED")); + } + // cmsReq.setResult(null); + return; + } + + private void downloadChain(String op, + IArgBlock args, + HttpServletRequest httpReq, + HttpServletResponse httpResp, + CMSRequest cmsReq) + throws EBaseException { + + /* check browser info ? */ + + /* check if pkcs7 will work for both nav and ie */ + + byte[] bytes = null; + + /* + * Some IE actions - IE doesn't want PKCS7 for "download" CA Cert. + * This means that we can only hand out the root CA, and not + * the whole chain. + */ + + if (clientIsMSIE(httpReq) && (op.equals("download") || op.equals("downloadBIN"))) { + X509Certificate[] caCerts = + ((ICertAuthority) mAuthority).getCACertChain().getChain(); + + try { + bytes = caCerts[0].getEncoded(); + } catch (CertificateEncodingException e) { + cmsReq.setStatus(CMSRequest.ERROR); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_GETTING_CACERT_ENCODED", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_GETTING_CA_CERT_ERROR")); + } + } else { + CertificateChain certChain = + ((ICertAuthority) mAuthority).getCACertChain(); + + if (certChain == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_CHAIN_EMPTY")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CA_CHAIN_EMPTY")); + } + + try { + ByteArrayOutputStream encoded = new ByteArrayOutputStream(); + + certChain.encode(encoded, false); + bytes = encoded.toByteArray(); + } catch (IOException e) { + cmsReq.setStatus(CMSRequest.ERROR); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_ENCODING_CA_CHAIN_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_CA_CHAIN_ERROR")); + } + } + + String mimeType = null; + + if (op.equals("downloadBIN")) { + mimeType = "application/octet-stream"; + } else { + try { + mimeType = args.getValueAsString("mimeType"); + } catch (EBaseException e) { + mimeType = "application/octet-stream"; + } + } + + try { + if (op.equals("downloadBIN")) { + // file suffixes changed to comply with RFC 5280 + // requirements for AIA extensions + if (clientIsMSIE(httpReq)) { + httpResp.setHeader("Content-disposition", + "attachment; filename=ca.cer"); + } else { + httpResp.setHeader("Content-disposition", + "attachment; filename=ca.p7c"); + } + } + httpResp.setContentType(mimeType); + httpResp.getOutputStream().write(bytes); + httpResp.setContentLength(bytes.length); + httpResp.getOutputStream().flush(); + } catch (IOException e) { + cmsReq.setStatus(CMSRequest.ERROR); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_DISPLAYING_CACHAIN_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAYING_CACHAIN_ERROR")); + } + } + + private void displayChain(String op, + IArgBlock args, + HttpServletRequest httpReq, + HttpServletResponse httpResp, + CMSRequest cmsReq) + throws EBaseException { + + CertificateChain certChain = + ((ICertAuthority) mAuthority).getCACertChain(); + + if (certChain == null) { + cmsReq.setStatus(CMSRequest.ERROR); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_CHAIN_NOT_AVAILABLE")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CA_CHAIN_NOT_AVAILABLE")); + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + String displayFormat = null; + + if (op.equals("displayIND")) { + displayFormat = "individual"; + } else { + try { + displayFormat = args.getValueAsString("displayFormat"); + } catch (EBaseException e) { + displayFormat = "chain"; + } + } + + header.addStringValue("displayFormat", displayFormat); + + if (displayFormat.equals("chain")) { + String subjectdn = null; + byte[] bytes = null; + + try { + subjectdn = + certChain.getFirstCertificate().getSubjectDN().toString(); + ByteArrayOutputStream encoded = new ByteArrayOutputStream(); + + certChain.encode(encoded); + bytes = encoded.toByteArray(); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_ENCODING_CA_CHAIN_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_CA_CHAIN_ERROR")); + } + + String chainBase64 = getBase64(bytes); + + header.addStringValue("subjectdn", subjectdn); + header.addStringValue("chainBase64", chainBase64); + } else { + try { + X509Certificate[] certs = certChain.getChain(); + + header.addIntegerValue("length", certs.length); + locale[0] = getLocale(httpReq); + for (int i = 0; i < certs.length; i++) { + byte[] bytes = null; + + try { + bytes = certs[i].getEncoded(); + } catch (CertificateEncodingException e) { + throw new IOException("Internal Error"); + } + String subjectdn = certs[i].getSubjectDN().toString(); + String finger = null; + try { + finger = CMS.getFingerPrints(certs[i]); + } catch (Exception e) { + throw new IOException("Internal Error"); + } + + ICertPrettyPrint certDetails = + CMS.getCertPrettyPrint((X509CertImpl) certs[i]); + + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("fingerprints", finger); + rarg.addStringValue("subjectdn", subjectdn); + rarg.addStringValue("base64", getBase64(bytes)); + rarg.addStringValue("certDetails", + certDetails.toString(locale[0])); + argSet.addRepeatRecord(rarg); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_DISPLAYING_CACHAIN_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAYING_CACHAIN_ERROR")); + } + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + + } + + /** + * gets base 64 encoded cert + */ + private String getBase64(byte[] certBytes) { + String certBase64 = CMS.BtoA(certBytes); + + return certBase64; + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/GetCRL.java b/base/common/src/com/netscape/cms/servlet/cert/GetCRL.java new file mode 100644 index 000000000..4c8661359 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/GetCRL.java @@ -0,0 +1,467 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRLException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CRLImpl; + +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.base.IArgBlock; +import com.netscape.certsrv.base.ICRLPrettyPrint; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Utils; + +/** + * Retrieve CRL for a Certificate Authority + * + * @version $Revision$, $Date$ + */ +public class GetCRL extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 7132206924070383013L; + private final static String TPL_FILE = "displayCRL.template"; + private String mFormPath = null; + + public GetCRL() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + mTemplates.remove(CMSRequest.SUCCESS); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + * @see DisplayCRL#process + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + if (!(mAuthority instanceof ICertificateAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + CMS.debug("**** mFormPath before getTemplate = " + mFormPath); + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + // Get the operation code + String op = null; + String crlId = null; + + op = args.getValueAsString("op", null); + crlId = args.getValueAsString("crlIssuingPoint", null); + if (op == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_OPTIONS_SELECTED")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_OPTIONS_SELECTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + if (crlId == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_CRL_SELECTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + ICRLIssuingPointRecord crlRecord = null; + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + ICRLIssuingPoint crlIP = null; + if (ca != null) + crlIP = ca.getCRLIssuingPoint(crlId); + + try { + crlRecord = (ICRLIssuingPointRecord) ca.getCRLRepository().readCRLIssuingPointRecord(crlId); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND", crlId)); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRL_NOT_FOUND"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + if (crlRecord == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlId)); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRL_NOT_UPDATED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + header.addStringValue("crlIssuingPoint", crlId); + header.addStringValue("crlNumber", crlRecord.getCRLNumber().toString()); + long lCRLSize = crlRecord.getCRLSize().longValue(); + + header.addLongValue("crlSize", lCRLSize); + if (crlIP != null) { + header.addStringValue("crlDescription", crlIP.getDescription()); + } + + String crlDisplayType = args.getValueAsString("crlDisplayType", null); + if (crlDisplayType != null) { + header.addStringValue("crlDisplayType", crlDisplayType); + } + + if ((op.equals("checkCRLcache") || + (op.equals("displayCRL") && crlDisplayType != null && crlDisplayType.equals("cachedCRL"))) && + (crlIP == null || (!crlIP.isCRLCacheEnabled()) || crlIP.isCRLCacheEmpty())) { + cmsReq.setError( + CMS.getUserMessage( + ((crlIP != null && crlIP.isCRLCacheEnabled() && crlIP.isCRLCacheEmpty()) ? + "CMS_GW_CRL_CACHE_IS_EMPTY" : "CMS_GW_CRL_CACHE_IS_NOT_ENABLED"), crlId)); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + byte[] crlbytes = null; + + if (op.equals("importDeltaCRL") || op.equals("getDeltaCRL") || + (op.equals("displayCRL") && crlDisplayType != null && + crlDisplayType.equals("deltaCRL"))) { + crlbytes = crlRecord.getDeltaCRL(); + } else if (op.equals("importCRL") || op.equals("getCRL") || + op.equals("checkCRL") || + (op.equals("displayCRL") && + crlDisplayType != null && + (crlDisplayType.equals("entireCRL") || + crlDisplayType.equals("crlHeader") || + crlDisplayType.equals("base64Encoded")))) { + crlbytes = crlRecord.getCRL(); + } + + if (crlbytes == null && (!op.equals("checkCRLcache")) && + (!(op.equals("displayCRL") && crlDisplayType != null && + crlDisplayType.equals("cachedCRL")))) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlId)); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRL_NOT_UPDATED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + byte[] bytes = crlbytes; + + X509CRLImpl crl = null; + + if (op.equals("checkCRL") || op.equals("importCRL") || + op.equals("importDeltaCRL") || + (op.equals("displayCRL") && crlDisplayType != null && + (crlDisplayType.equals("entireCRL") || + crlDisplayType.equals("crlHeader") || + crlDisplayType.equals("base64Encoded") || + crlDisplayType.equals("deltaCRL")))) { + try { + if (op.equals("displayCRL") && crlDisplayType != null && + crlDisplayType.equals("crlHeader")) { + crl = new X509CRLImpl(crlbytes, false); + } else { + crl = new X509CRLImpl(crlbytes); + } + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_FAILED_DECODE_CRL_1", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DECODE_CRL_FAILED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + if ((op.equals("importDeltaCRL") || (op.equals("displayCRL") && + crlDisplayType != null && crlDisplayType.equals("deltaCRL"))) && + ((!(crlIP != null && crlIP.isThisCurrentDeltaCRL(crl))) && + (crlRecord.getCRLNumber() == null || + crlRecord.getDeltaCRLNumber() == null || + crlRecord.getDeltaCRLNumber().compareTo(crlRecord.getCRLNumber()) < 0 || + crlRecord.getDeltaCRLSize() == null || + crlRecord.getDeltaCRLSize().longValue() == -1))) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_NO_DELTA_CRL_1")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRL_NOT_UPDATED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + } + + String mimeType = "application/x-pkcs7-crl"; + + if (op.equals("checkCRLcache") || op.equals("checkCRL") || op.equals("displayCRL")) { + header.addStringValue("toDo", op); + String certSerialNumber = args.getValueAsString("certSerialNumber", ""); + + header.addStringValue("certSerialNumber", certSerialNumber); + if (certSerialNumber.startsWith("0x")) { + certSerialNumber = hexToDecimal(certSerialNumber); + } + + if (op.equals("checkCRLcache")) { + if (crlIP.getRevocationDateFromCache( + new BigInteger(certSerialNumber), false, false) != null) { + header.addBooleanValue("isOnCRL", true); + } else { + header.addBooleanValue("isOnCRL", false); + } + } + + if (op.equals("checkCRL")) { + header.addBooleanValue("isOnCRL", + crl.isRevoked(new BigInteger(certSerialNumber))); + } + + if (op.equals("displayCRL")) { + if (crlDisplayType.equals("entireCRL") || crlDisplayType.equals("cachedCRL")) { + ICRLPrettyPrint crlDetails = (crlDisplayType.equals("entireCRL")) ? + CMS.getCRLPrettyPrint(crl) : + CMS.getCRLCachePrettyPrint(crlIP); + String pageStart = args.getValueAsString("pageStart", null); + String pageSize = args.getValueAsString("pageSize", null); + + if (pageStart != null && pageSize != null) { + long lPageStart = new Long(pageStart).longValue(); + long lPageSize = new Long(pageSize).longValue(); + + if (lPageStart < 1) + lPageStart = 1; + + header.addStringValue("crlPrettyPrint", + crlDetails.toString(locale[0], + lCRLSize, lPageStart, lPageSize)); + header.addLongValue("pageStart", lPageStart); + header.addLongValue("pageSize", lPageSize); + } else { + header.addStringValue( + "crlPrettyPrint", crlDetails.toString(locale[0])); + } + } else if (crlDisplayType.equals("crlHeader")) { + ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(crl); + + header.addStringValue( + "crlPrettyPrint", crlDetails.toString(locale[0], lCRLSize, 0, 0)); + } else if (crlDisplayType.equals("base64Encoded")) { + try { + byte[] ba = crl.getEncoded(); + String crlBase64Encoded = Utils.base64encode(ba); + int length = crlBase64Encoded.length(); + int i = 0; + int j = 0; + int n = 1; + + while (i < length) { + int k = crlBase64Encoded.indexOf('\n', i); + + if (n < 100 && k > -1) { + n++; + i = k + 1; + } else { + n = 1; + IArgBlock rarg = CMS.createArgBlock(); + + if (k > -1) { + rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k)); + i = k + 1; + j = i; + } else { + rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, length)); + i = length; + } + argSet.addRepeatRecord(rarg); + } + } + } catch (CRLException e) { + } + } else if (crlDisplayType.equals("deltaCRL")) { + header.addIntegerValue("deltaCRLSize", + crl.getNumberOfRevokedCertificates()); + + ICRLPrettyPrint crlDetails = CMS.getCRLPrettyPrint(crl); + + header.addStringValue( + "crlPrettyPrint", crlDetails.toString(locale[0], 0, 0, 0)); + + try { + byte[] ba = crl.getEncoded(); + String crlBase64Encoded = Utils.base64encode(ba); + int length = crlBase64Encoded.length(); + int i = 0; + int j = 0; + int n = 1; + + while (i < length) { + int k = crlBase64Encoded.indexOf('\n', i); + + if (n < 100 && k > -1) { + n++; + i = k + 1; + } else { + n = 1; + IArgBlock rarg = CMS.createArgBlock(); + + if (k > -1) { + rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, k)); + i = k + 1; + j = i; + } else { + rarg.addStringValue("crlBase64Encoded", crlBase64Encoded.substring(j, length)); + i = length; + } + argSet.addRepeatRecord(rarg); + } + } + } catch (CRLException e) { + } + } + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + return; + } else if (op.equals("importCRL") || op.equals("importDeltaCRL")) { + if (clientIsMSIE(httpReq)) + mimeType = "application/pkix-crl"; + else + mimeType = "application/x-pkcs7-crl"; + } else if (op.equals("getCRL")) { + mimeType = "application/octet-stream"; + httpResp.setHeader("Content-disposition", + "attachment; filename=" + crlId + ".crl"); + } else if (op.equals("getDeltaCRL")) { + mimeType = "application/octet-stream"; + httpResp.setHeader("Content-disposition", + "attachment; filename=delta-" + crlId + ".crl"); + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_OPTIONS_SELECTED")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_OPTIONS_SELECTED")); + } + + try { + // if (clientIsMSIE(httpReq) && op.equals("getCRL")) + // httpResp.setHeader("Content-disposition", + // "attachment; filename=getCRL.crl"); + httpResp.setContentType(mimeType); + httpResp.setContentLength(bytes.length); + httpResp.getOutputStream().write(bytes); + httpResp.getOutputStream().flush(); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_DISPLAYING_CRLINFO")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAYING_CRLINFO_ERROR")); + } + // cmsReq.setResult(null); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + private String hexToDecimal(String hex) { + String newHex = hex.substring(2); + BigInteger bi = new BigInteger(newHex, 16); + + return bi.toString(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java b/base/common/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java new file mode 100644 index 000000000..71b0004cd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java @@ -0,0 +1,350 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Locale; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.Extension; +import netscape.security.x509.KeyUsageExtension; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; + +/** + * Gets a issued certificate from a request id. + * + * @version $Revision$, $Date$ + */ +public class GetCertFromRequest extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 5310646832256611066L; + private final static String PROP_IMPORT = "importCert"; + protected static final String GET_CERT_FROM_REQUEST_TEMPLATE = "ImportCert.template"; + protected static final String DISPLAY_CERT_FROM_REQUEST_TEMPLATE = "displayCertFromRequest.template"; + + protected static final String REQUEST_ID = "requestId"; + protected static final String CERT_TYPE = "certtype"; + + protected String mCertFrReqSuccessTemplate = null; + protected ICMSTemplateFiller mCertFrReqFiller = null; + + protected IRequestQueue mQueue = null; + protected boolean mImportCert = true; + + public GetCertFromRequest() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template files + * "displayCertFromRequest.template" and "ImportCert.template" + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mTemplates.remove(CMSRequest.SUCCESS); + mQueue = mAuthority.getRequestQueue(); + try { + String tmp = sc.getInitParameter( + PROP_IMPORT); + + if (tmp != null && tmp.trim().equalsIgnoreCase("false")) + mImportCert = false; + + String defTemplate = null; + + if (mImportCert) + defTemplate = GET_CERT_FROM_REQUEST_TEMPLATE; + else + defTemplate = DISPLAY_CERT_FROM_REQUEST_TEMPLATE; + if (mAuthority instanceof IRegistrationAuthority) + defTemplate = "/ra/" + defTemplate; + else + defTemplate = "/ca/" + defTemplate; + mCertFrReqSuccessTemplate = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE); + if (mCertFrReqSuccessTemplate == null) + mCertFrReqSuccessTemplate = defTemplate; + String fillername = + sc.getInitParameter(PROP_SUCCESS_TEMPLATE_FILLER); + + if (fillername != null) { + ICMSTemplateFiller filler = newFillerObject(fillername); + + if (filler != null) + mCertFrReqFiller = filler; + } else { + mCertFrReqFiller = new CertFrRequestFiller(); + } + } catch (Exception e) { + // should never happen. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(), + mId)); + } + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param requestId The request ID to search on + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + IArgBlock httpParams = cmsReq.getHttpParams(); + HttpServletRequest httpReq = cmsReq.getHttpReq(); + + IAuthToken authToken = authenticate(cmsReq); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String requestId = httpParams.getValueAsString(REQUEST_ID, null); + + if (requestId == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_REQUEST_ID_PROVIDED")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_REQUEST_ID_PROVIDED")); + } + // check if request Id is valid. + try { + new BigInteger(requestId); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_REQ_ID_FORMAT", requestId)); + throw new EBaseException( + CMS.getUserMessage(getLocale(httpReq), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId)); + } + + IRequest r = mQueue.findRequest(new RequestId(requestId)); + + if (r == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQUEST_ID_NOT_FOUND", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_ID_NOT_FOUND", requestId)); + } + + if (authToken != null) { + //if RA, group and requestOwner must match + String group = authToken.getInString("group"); + if ((group != null) && (group != "") && + group.equals("Registration Manager Agents")) { + boolean groupMatched = false; + String reqOwner = r.getRequestOwner(); + if (reqOwner != null) { + CMS.debug("GetCertFromRequest process: req owner=" + reqOwner); + if (reqOwner.equals(group)) + groupMatched = true; + } + if (groupMatched == false) { + CMS.debug("RA group unmatched"); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQUEST_ID_NOT_FOUND", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_ID_NOT_FOUND", requestId)); + } + } + } + + if (!((r.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) || + (r.getRequestType().equals(IRequest.RENEWAL_REQUEST)))) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQUEST_NOT_ENROLLMENT_1", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_NOT_ENROLLMENT", requestId)); + } + RequestStatus status = r.getRequestStatus(); + + if (!status.equals(RequestStatus.COMPLETE)) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQUEST_NOT_COMPLETED_1", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_NOT_COMPLETED", requestId)); + } + Integer result = r.getExtDataInInteger(IRequest.RESULT); + + if (result != null && !result.equals(IRequest.RES_SUCCESS)) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQUEST_HAD_ERROR_1", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_HAD_ERROR", requestId)); + } + Object o = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (r.getExtDataInString("profile") != null) { + // handle profile-based request + X509CertImpl cert = r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); + X509CertImpl certs[] = new X509CertImpl[1]; + + certs[0] = cert; + o = certs; + } + if (o == null || !(o instanceof X509CertImpl[])) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQUEST_HAD_NO_CERTS_1", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_HAD_NO_CERTS", requestId)); + } + if (o instanceof X509CertImpl[]) { + X509CertImpl[] certs = (X509CertImpl[]) o; + + if (certs == null || certs.length == 0 || certs[0] == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQUEST_HAD_NO_CERTS_1", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_HAD_NO_CERTS", requestId)); + } + + // for importsCert to get the crmf_reqid. + cmsReq.setIRequest(r); + + cmsReq.setStatus(CMSRequest.SUCCESS); + + if (mImportCert && + checkImportCertToNav(cmsReq.getHttpResp(), httpParams, certs[0])) { + return; + } + try { + cmsReq.setResult(certs); + renderTemplate(cmsReq, mCertFrReqSuccessTemplate, mCertFrReqFiller); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGE_ERROR_DISPLAY_TEMPLATE_1", + mCertFrReqSuccessTemplate, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + return; + } +} + +class CertFrRequestFiller extends ImportCertsTemplateFiller { + public CertFrRequestFiller() { + } + + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) + throws Exception { + CMSTemplateParams tparams = + super.getTemplateParams(cmsReq, authority, locale, e); + String reqId = cmsReq.getHttpParams().getValueAsString( + GetCertFromRequest.REQUEST_ID); + + tparams.getHeader().addStringValue(GetCertFromRequest.REQUEST_ID, reqId); + + if (reqId != null) { + IRequest r = authority.getRequestQueue().findRequest(new RequestId(reqId)); + if (r != null) { + boolean noCertImport = true; + String certType = r.getExtDataInString(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE); + + if (certType != null && certType.equals(IRequest.CLIENT_CERT)) { + noCertImport = false; + } + tparams.getHeader().addBooleanValue("noCertImport", noCertImport); + + X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (certs != null) { + X509CertInfo info = (X509CertInfo) certs[0].get(X509CertImpl.NAME + "." + X509CertImpl.INFO); + CertificateExtensions extensions = (CertificateExtensions) info.get(X509CertInfo.EXTENSIONS); + + tparams.getHeader().addStringValue(GetCertFromRequest.CERT_TYPE, "x509"); + + boolean emailCert = false; + + if (extensions != null) { + for (int i = 0; i < extensions.size(); i++) { + Extension ext = (Extension) extensions.elementAt(i); + + if (ext instanceof NSCertTypeExtension) { + NSCertTypeExtension type = (NSCertTypeExtension) ext; + + if (((Boolean) type.get(NSCertTypeExtension.EMAIL)).booleanValue()) + emailCert = true; + } + if (ext instanceof KeyUsageExtension) { + KeyUsageExtension usage = + (KeyUsageExtension) ext; + + try { + if (((Boolean) usage.get(KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue() || + ((Boolean) usage.get(KeyUsageExtension.DATA_ENCIPHERMENT)).booleanValue()) + emailCert = true; + } catch (ArrayIndexOutOfBoundsException e0) { + // bug356108: + // In case there is only DIGITAL_SIGNATURE, + // don't report error + } + } + } + } + tparams.getHeader().addBooleanValue("emailCert", emailCert); + } + } + } + + return tparams; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/GetEnableStatus.java b/base/common/src/com/netscape/cms/servlet/cert/GetEnableStatus.java new file mode 100644 index 000000000..d0dfb8f9a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/GetEnableStatus.java @@ -0,0 +1,173 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.cms.authentication.HashAuthentication; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Servlet to get the enrollment status, enable or disable. + * + * @version $Revision$, $Date$ + */ +public class GetEnableStatus extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 3879769989681379834L; + private final static String TPL_FILE = "userEnroll.template"; + private String mFormPath = null; + + public GetEnableStatus() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // coming from agent + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + protected CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String reqHost = httpReq.getRemoteHost(); + + if (!(mAuthority instanceof IRegistrationAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", + mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IConfigStore configStore = CMS.getConfigStore(); + String val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr; + long timeout = HashAuthentication.DEFAULT_TIMEOUT / 1000; + + header.addStringValue("timeout", "" + timeout); + header.addStringValue("reqHost", reqHost); + + for (Enumeration<String> hosts = mgr.getHosts(); hosts.hasMoreElements();) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("hosts", hosts.nextElement()); + argSet.addRepeatRecord(rarg); + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/GetInfo.java b/base/common/src/com/netscape/cms/servlet/cert/GetInfo.java new file mode 100644 index 000000000..6af5c0c39 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/GetInfo.java @@ -0,0 +1,377 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.AlgorithmId; + +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.base.IArgBlock; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.dbs.crldb.ICRLRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Get detailed information about CA CRL processing + * + * @version $Revision$, $Date$ + */ +public class GetInfo extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1909881831730252799L; + + private final static String INFO = "GetInfo"; + + private String mFormPath = null; + private ICertificateAuthority mCA = null; + + /** + * Constructs GetInfo servlet. + */ + public GetInfo() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + mFormPath = ""; + if (mAuthority instanceof ICertificateAuthority) + mCA = (ICertificateAuthority) mAuthority; + + // override success to do output our own template. + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * XXX Process the HTTP request. + * <ul> + * <li>http.param template filename of template to use to render the result + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + EBaseException error = null; + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + String template = req.getParameter("template"); + String formFile = ""; + + /* + for (int i = 0; ((template != null) && (i < template.length())); i++) { + char c = template.charAt(i); + if (!Character.isLetterOrDigit(c) && c != '_' && c != '-') { + template = null; + break; + } + } + */ + + if (template != null) { + formFile = template + ".template"; + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE_1")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + CMS.debug("*** formFile = " + formFile); + try { + form = getTemplate(formFile, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", formFile, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + process(argSet, header, req, resp, locale[0]); + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + private void process(CMSTemplateParams argSet, IArgBlock header, + HttpServletRequest req, + HttpServletResponse resp, + Locale locale) + throws EBaseException { + if (mCA != null) { + String crlIssuingPoints = ""; + String crlNumbers = ""; + String deltaNumbers = ""; + String crlSizes = ""; + String deltaSizes = ""; + String crlDescriptions = ""; + StringBuffer crlSplits = new StringBuffer(); + String recentChanges = ""; + String crlTesting = ""; + boolean isDeltaCRLEnabled = false; + + String masterHost = CMS.getConfigStore().getString("master.ca.agent.host", ""); + String masterPort = CMS.getConfigStore().getString("master.ca.agent.port", ""); + + if (masterHost != null && masterHost.length() > 0 && + masterPort != null && masterPort.length() > 0) { + + ICRLRepository crlRepository = mCA.getCRLRepository(); + + Vector<String> ipNames = crlRepository.getIssuingPointsNames(); + for (int i = 0; i < ipNames.size(); i++) { + String ipName = ipNames.elementAt(i); + ICRLIssuingPointRecord crlRecord = null; + try { + crlRecord = crlRepository.readCRLIssuingPointRecord(ipName); + } catch (Exception e) { + } + if (crlRecord != null) { + if (crlIssuingPoints.length() > 0) + crlIssuingPoints += "+"; + crlIssuingPoints += ipName; + + BigInteger crlNumber = crlRecord.getCRLNumber(); + if (crlNumbers.length() > 0) + crlNumbers += "+"; + if (crlNumber != null) + crlNumbers += crlNumber.toString(); + + if (crlSizes.length() > 0) + crlSizes += "+"; + crlSizes += ((crlRecord.getCRLSize() != null) ? + crlRecord.getCRLSize().toString() : "-1"); + + if (deltaSizes.length() > 0) + deltaSizes += "+"; + long dSize = -1; + if (crlRecord.getDeltaCRLSize() != null) + dSize = crlRecord.getDeltaCRLSize().longValue(); + deltaSizes += dSize; + + BigInteger deltaNumber = crlRecord.getDeltaCRLNumber(); + if (deltaNumbers.length() > 0) + deltaNumbers += "+"; + if (deltaNumber != null && dSize > -1) { + deltaNumbers += deltaNumber.toString(); + isDeltaCRLEnabled |= true; + } else { + deltaNumbers += "0"; + } + + if (recentChanges.length() > 0) + recentChanges += "+"; + recentChanges += "-, -, -"; + + if (crlTesting.length() > 0) + crlTesting += "+"; + crlTesting += "0"; + } + } + + } else { + Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = ips.nextElement(); + + if (ip.isCRLIssuingPointEnabled()) { + if (crlIssuingPoints.length() > 0) + crlIssuingPoints += "+"; + crlIssuingPoints += ip.getId(); + + BigInteger crlNumber = ip.getCRLNumber(); + if (crlNumbers.length() > 0) + crlNumbers += "+"; + if (crlNumber != null) + crlNumbers += crlNumber.toString(); + + BigInteger deltaNumber = ip.getDeltaCRLNumber(); + if (deltaNumbers.length() > 0) + deltaNumbers += "+"; + if (deltaNumber != null) + deltaNumbers += deltaNumber.toString(); + + if (crlSizes.length() > 0) + crlSizes += "+"; + crlSizes += ip.getCRLSize(); + + if (deltaSizes.length() > 0) + deltaSizes += "+"; + deltaSizes += ip.getDeltaCRLSize(); + + if (crlDescriptions.length() > 0) + crlDescriptions += "+"; + crlDescriptions += ip.getDescription(); + + if (recentChanges.length() > 0) + recentChanges += "+"; + if (ip.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_PUBLISHING_STARTED) { + recentChanges += "Publishing CRL #" + ip.getCRLNumber(); + } else if (ip.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_UPDATE_STARTED) { + recentChanges += "Creating CRL #" + ip.getNextCRLNumber(); + } else { // ip.CRL_UPDATE_DONE + recentChanges += ip.getNumberOfRecentlyRevokedCerts() + ", " + + ip.getNumberOfRecentlyUnrevokedCerts() + ", " + + ip.getNumberOfRecentlyExpiredCerts(); + } + isDeltaCRLEnabled |= ip.isDeltaCRLEnabled(); + + if (crlSplits.length() > 0) + crlSplits.append("+"); + Vector<Long> splits = ip.getSplitTimes(); + + for (int i = 0; i < splits.size(); i++) { + crlSplits.append(splits.elementAt(i)); + if (i + 1 < splits.size()) + crlSplits.append(","); + } + + if (crlTesting.length() > 0) + crlTesting += "+"; + crlTesting += ((ip.isCRLCacheTestingEnabled()) ? "1" : "0"); + } + } + + } + + header.addStringValue("crlIssuingPoints", crlIssuingPoints); + header.addStringValue("crlDescriptions", crlDescriptions); + header.addStringValue("crlNumbers", crlNumbers); + header.addStringValue("deltaNumbers", deltaNumbers); + header.addStringValue("crlSizes", crlSizes); + header.addStringValue("deltaSizes", deltaSizes); + header.addStringValue("crlSplits", crlSplits.toString()); + header.addStringValue("crlTesting", crlTesting); + header.addBooleanValue("isDeltaCRLEnabled", isDeltaCRLEnabled); + + header.addStringValue("master_host", masterHost); + header.addStringValue("master_port", masterPort); + + header.addStringValue("masterCRLIssuingPoint", ICertificateAuthority.PROP_MASTER_CRL); + ICRLIssuingPoint ip0 = mCA.getCRLIssuingPoint(ICertificateAuthority.PROP_MASTER_CRL); + + if (ip0 != null) { + header.addStringValue("defaultAlgorithm", ip0.getSigningAlgorithm()); + } + + if (recentChanges.length() > 0) + header.addStringValue("recentChanges", recentChanges); + + String validAlgorithms = null; + String[] allAlgorithms = mCA.getCASigningAlgorithms(); + + if (allAlgorithms == null) { + CMS.debug("GetInfo: signing algorithms set to All algorithms"); + allAlgorithms = AlgorithmId.ALL_SIGNING_ALGORITHMS; + } + + for (int i = 0; i < allAlgorithms.length; i++) { + if (i > 0) { + validAlgorithms += "+" + allAlgorithms[i]; + } else { + validAlgorithms = allAlgorithms[i]; + } + } + if (validAlgorithms != null) + header.addStringValue("validAlgorithms", validAlgorithms); + } + + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java b/base/common/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java new file mode 100644 index 000000000..5e6207e1a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java @@ -0,0 +1,1241 @@ +// --- 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.cert; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.KeyUsageExtension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertRecordList; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.authentication.HashAuthentication; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; + +/** + * performs face-to-face enrollment. + * + * @version $Revision$, $Date$ + */ +public class HashEnrollServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 5532936020515258333L; + + public final static String ADMIN_ENROLL_SERVLET_ID = "adminEnroll"; + + // enrollment templates. + public static final String ENROLL_SUCCESS_TEMPLATE = "/ra/HashEnrollSuccess.template"; + + // http params + public static final String OLD_CERT_TYPE = "csrCertType"; + public static final String CERT_TYPE = "certType"; + // same as in ConfigConstant.java + public static final String REQUEST_FORMAT = "reqFormat"; + public static final String REQUEST_CONTENT = "requestContent"; + public static final String SUBJECT_KEYGEN_INFO = "subjectKeyGenInfo"; + public static final String CRMF_REQUEST = "CRMFRequest"; + public static final String SUBJECT_NAME = "subject"; + public static final String CRMF_REQID = "crmfReqId"; + public static final String CHALLENGE_PASSWORD = "challengePhrase"; + + private static final String CERT_AUTH_DUAL = "dual"; + private static final String CERT_AUTH_ENCRYPTION = "encryption"; + private static final String CERT_AUTH_SINGLE = "single"; + private static final String CLIENT_ISSUER = "clientIssuer"; + public static final String TPL_ERROR_FILE = "/ra/GenErrorHashDirEnroll.template"; + + private boolean mAuthTokenOverride = true; + private String mEnrollSuccessTemplate = null; + private ICMSTemplateFiller mEnrollSuccessFiller = new ImportCertsTemplateFiller(); + + ICertificateAuthority mCa = null; + ICertificateRepository mRepository = null; + + public HashEnrollServlet() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success template to allow direct import of keygen certs. + mTemplates.remove(CMSRequest.SUCCESS); + try { + mEnrollSuccessTemplate = sc.getInitParameter( + CMSServlet.PROP_SUCCESS_TEMPLATE); + if (mEnrollSuccessTemplate == null) + mEnrollSuccessTemplate = ENROLL_SUCCESS_TEMPLATE; + String fillername = + sc.getInitParameter(PROP_SUCCESS_TEMPLATE_FILLER); + + if (fillername != null) { + ICMSTemplateFiller filler = newFillerObject(fillername); + + if (filler != null) + mEnrollSuccessFiller = filler; + } + + // cfu + mCa = (ICertificateAuthority) CMS.getSubsystem("ca"); + + init_testbed_hack(mConfig); + } catch (Exception e) { + // this should never happen. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(), mId)); + } + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + IArgBlock httpParams = cmsReq.getHttpParams(); + HttpServletRequest httpReq = cmsReq.getHttpReq(); + String certType = null; + + String reqHost = httpReq.getRemoteHost(); + + String host = httpParams.getValueAsString("hostname", null); + + if (host == null || !host.equals(reqHost)) { + printError(cmsReq, "0"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + IConfigStore configStore = CMS.getConfigStore(); + String val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr; + + Date date = new Date(); + long currTime = date.getTime(); + long timeout = mgr.getTimeout(reqHost); + long lastlogin = mgr.getLastLogin(reqHost); + long diff = currTime - lastlogin; + + boolean enable = mgr.isEnable(reqHost); + + if (!enable) { + printError(cmsReq, "0"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + if (lastlogin == 0) + mgr.setLastLogin(reqHost, currTime); + else if (diff > timeout) { + mgr.disable(reqHost); + printError(cmsReq, "2"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + mgr.setLastLogin(reqHost, currTime); + + // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType + // instead of certType + certType = httpParams.getValueAsString(OLD_CERT_TYPE, null); + if (certType == null) { + certType = httpParams.getValueAsString(CERT_TYPE, "client"); + } else { + ; + } + + processX509(cmsReq); + } + + private void printError(CMSRequest cmsReq, String errorCode) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + mTemplates.remove(CMSRequest.SUCCESS); + header.addStringValue("authority", "Registration Manager"); + header.addStringValue("errorCode", errorCode); + String formPath = TPL_ERROR_FILE; + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(formPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", formPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", + e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + } + + protected void processX509(CMSRequest cmsReq) + throws EBaseException { + IArgBlock httpParams = cmsReq.getHttpParams(); + HttpServletRequest httpReq = cmsReq.getHttpReq(); + + // create enrollment request in request queue. + IRequest req = mRequestQueue.newRequest(IRequest.ENROLLMENT_REQUEST); + + /* + * === certAuth based enroll === + * "certAuthEnroll" is on. + * "certauthEnrollType can be one of the three: + * single - it's for single cert enrollment + * dual - it's for dual certs enrollment + * encryption - getting the encryption cert only via + * authentication of the signing cert + * (crmf or keyGenInfo) + */ + boolean certAuthEnroll = false; + + String certAuthEnrollOn = + httpParams.getValueAsString("certauthEnroll", null); + + if ((certAuthEnrollOn != null) && (certAuthEnrollOn.equals("on"))) { + certAuthEnroll = true; + CMS.debug("HashEnrollServlet: certAuthEnroll is on"); + } + + String certauthEnrollType = null; + + if (certAuthEnroll == true) { + certauthEnrollType = + httpParams.getValueAsString("certauthEnrollType", null); + if (certauthEnrollType != null) { + if (certauthEnrollType.equals("dual")) { + CMS.debug("HashEnrollServlet: certauthEnrollType is dual"); + } else if (certauthEnrollType.equals("encryption")) { + CMS.debug("HashEnrollServlet: certauthEnrollType is encryption"); + } else if (certauthEnrollType.equals("single")) { + CMS.debug("HashEnrollServlet: certauthEnrollType is single"); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_CERTAUTH_ENROLL_TYPE_1", certauthEnrollType)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERTAUTH_ENROLL_TYPE")); + } + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTAUTH_ENROLL_TYPE")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CERTAUTH_ENROLL_TYPE")); + } + } + + String challengePassword = httpParams.getValueAsString("challengePassword", ""); + + cmsReq.setIRequest(req); + saveHttpHeaders(httpReq, req); + saveHttpParams(httpParams, req); + IAuthToken token = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, token, + mAuthzResourceName, "import"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + X509Certificate sslClientCert = null; + // cert auth enroll + String certBasedOldSubjectDN = null; + BigInteger certBasedOldSerialNum = null; + + // check if request was authenticated, if so set authtoken & certInfo. + // also if authenticated, take certInfo from authToken. + X509CertInfo certInfo = null; + + if (certAuthEnroll == true) { + sslClientCert = getSSLClientCertificate(httpReq); + if (sslClientCert == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_SSL_CLIENT_CERT")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SSL_CLIENT_CERT")); + } + + certBasedOldSubjectDN = (String) sslClientCert.getSubjectDN().toString(); + certBasedOldSerialNum = (BigInteger) sslClientCert.getSerialNumber(); + try { + certInfo = (X509CertInfo) + ((X509CertImpl) sslClientCert).get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + } catch (CertificateParsingException ex) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTINFO_ENCRYPT_CERT")); + throw new ECMSGWException( + CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_CERTINFO")); + } + } else { + certInfo = CMS.getDefaultX509CertInfo(); + } + + X509CertInfo[] certInfoArray = new X509CertInfo[] { certInfo }; + + //AuthToken authToken = access.getAuthToken(); + IConfigStore configStore = CMS.getConfigStore(); + String val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr1 = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr1; + String pageID = httpParams.getValueAsString("pageID", null); + + IAuthToken authToken = mgr.getAuthToken(pageID); + + String authMgr = AuditFormat.NOAUTH; + + if (authToken == null) { + printError(cmsReq, "3"); + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } else { + authMgr = + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + // don't store agent token in request. + // agent currently used for bulk issuance. + // if (!authMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + log(ILogger.LL_INFO, + "Enrollment request was authenticated by " + + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME)); + fillCertInfoFromAuthToken(certInfo, authToken); + // save authtoken attrs to request directly (for policy use) + saveAuthToken(authToken, req); + // req.set(IRequest.AUTH_TOKEN, authToken); + // } + } + + // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType + // instead of certType + String certType = httpParams.getValueAsString(OLD_CERT_TYPE, null); + if (certType == null) { + certType = httpParams.getValueAsString(CERT_TYPE, "client"); + } else { + // some policies may rely on the fact that + // CERT_TYPE is set. So for 3.5.1 or eariler + // we need to set CERT_TYPE here. + req.setExtData(IRequest.HTTP_PARAMS, CERT_TYPE, certType); + } + + String crmf = + httpParams.getValueAsString(CRMF_REQUEST, null); + + if (certAuthEnroll == true) { + + fillCertInfoFromAuthToken(certInfo, authToken); + + // for dual certs + if (certauthEnrollType.equals(CERT_AUTH_DUAL)) { + if (mCa == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NOT_A_CA")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_A_CA")); + } + + // first, make sure the client cert is indeed a + // signing only cert + if ((CMS.isSigningCert((X509CertImpl) sslClientCert) == + false) || + ((CMS.isSigningCert((X509CertImpl) sslClientCert) == + true) && + (CMS.isEncryptionCert((X509CertImpl) sslClientCert) == + true))) { + // either it's not a signing cert, or it's a dual cert + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_CERT_TYPE")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERT_TYPE")); + } + X509Key key = null; + + // for signing cert + key = (X509Key) sslClientCert.getPublicKey(); + try { + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } + + String filter = + "(&(x509cert.subject=" + + certBasedOldSubjectDN + ")(!(x509cert.serialNumber=" + certBasedOldSerialNum + + "))(certStatus=VALID))"; + ICertRecordList list = + (ICertRecordList) mCa.getCertificateRepository().findCertRecordsInList(filter, + null, 10); + int size = list.getSize(); + Enumeration<ICertRecord> en = list.getCertRecords(0, size - 1); + boolean gotEncCert = false; + + if (!en.hasMoreElements()) { + // pairing encryption cert not found + } else { + X509CertInfo encCertInfo = CMS.getDefaultX509CertInfo(); + X509CertInfo[] cInfoArray = new X509CertInfo[] { certInfo, + encCertInfo }; + int i = 1; + + while (en.hasMoreElements()) { + ICertRecord record = en.nextElement(); + X509CertImpl cert = record.getCertificate(); + + // if not encryption cert only, try next one + if ((CMS.isEncryptionCert(cert) == false) || + ((CMS.isEncryptionCert(cert) == true) && + (CMS.isSigningCert(cert) == true))) { + continue; + } + + key = (X509Key) cert.getPublicKey(); + try { + encCertInfo = (X509CertInfo) + cert.get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + + } catch (CertificateParsingException ex) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTINFO_ENCRYPT_CERT")); + throw new ECMSGWException( + CMS.getUserMessage(getLocale(httpReq), "CMS_GW_MISSING_CERTINFO")); + } + + try { + encCertInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_CERT_AUTH_ENROLL_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_CERT_AUTH_ENROLL_FAILED", e.toString())); + } + fillCertInfoFromAuthToken(encCertInfo, authToken); + + cInfoArray[i++] = encCertInfo; + certInfoArray = cInfoArray; + gotEncCert = true; + break; + } + } + + if (gotEncCert == false) { + // encryption cert not found, bail + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ENCRYPTION_CERT_NOT_FOUND")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCRYPTION_CERT_NOT_FOUND")); + } + } else if (certauthEnrollType.equals(CERT_AUTH_ENCRYPTION)) { + // first, make sure the client cert is indeed a + // signing only cert + if ((CMS.isSigningCert((X509CertImpl) sslClientCert) == + false) || + ((CMS.isSigningCert((X509CertImpl) sslClientCert) == + true) && + (CMS.isEncryptionCert((X509CertImpl) sslClientCert) == + true))) { + // either it's not a signing cert, or it's a dual cert + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_CERT_TYPE")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERT_TYPE")); + } + + /* + * crmf + */ + if (crmf != null && crmf != "") { + certInfoArray = fillCRMF(crmf, authToken, httpParams, req); + req.setExtData(CLIENT_ISSUER, + sslClientCert.getIssuerDN().toString()); + CMS.debug( + "HashEnrollServlet: sslClientCert issuerDN = " + sslClientCert.getIssuerDN().toString()); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO")); + throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq), + "CMS_GW_MISSING_KEYGEN_INFO")); + } + } else if (certauthEnrollType.equals(CERT_AUTH_SINGLE)) { + // have to be buried here to handle the issuer + + if (crmf != null && crmf != "") { + certInfoArray = fillCRMF(crmf, authToken, httpParams, req); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO")); + throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq), + "CMS_GW_MISSING_KEYGEN_INFO")); + } + req.setExtData(CLIENT_ISSUER, + sslClientCert.getIssuerDN().toString()); + } + } else if (crmf != null && crmf != "") { + certInfoArray = fillCRMF(crmf, authToken, httpParams, req); + } else { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_KEYGEN_INFO")); + throw new ECMSGWException(CMS.getUserMessage(getLocale(httpReq), + "CMS_GW_MISSING_KEYGEN_INFO")); + } + + req.setExtData(IRequest.CERT_INFO, certInfoArray); + + if (challengePassword != null && !challengePassword.equals("")) { + String pwd = hashPassword(challengePassword); + + req.setExtData(CHALLENGE_PASSWORD, pwd); + } + + // send request to request queue. + mRequestQueue.processRequest(req); + // process result. + + // render OLD_CERT_TYPE's response differently, we + // dont want any javascript in HTML, and need to + // override the default render. + if (httpParams.getValueAsString(OLD_CERT_TYPE, null) != null) { + try { + renderServerEnrollResult(cmsReq); + cmsReq.setStatus(CMSRequest.SUCCESS); // no default render + } catch (IOException ex) { + cmsReq.setStatus(CMSRequest.ERROR); + } + return; + } + + //for audit log + String initiative = null; + String agentID = null; + + if (!authMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + // request is from eegateway, so fromUser. + initiative = AuditFormat.FROMUSER; + } else { + agentID = authToken.getInString("userid"); + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID; + } + + // if service not complete return standard templates. + RequestStatus status = req.getRequestStatus(); + + if (status != RequestStatus.COMPLETE) { + cmsReq.setIRequestStatus(); // set status acc. to IRequest status. + // audit log the status + try { + if (status == RequestStatus.REJECTED) { + Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration<String> msgs = messages.elements(); + StringBuffer wholeMsg = new StringBuffer(); + + while (msgs.hasMoreElements()) { + wholeMsg.append("\n"); + wholeMsg.append(msgs.nextElement()); + } + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + certInfo.get(X509CertInfo.SUBJECT), + " violation: " + + wholeMsg.toString() }, + ILogger.L_MULTILINE + ); + } else { // no policy violation, from agent + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + certInfo.get(X509CertInfo.SUBJECT), "" } + ); + } + } else { // other imcomplete status + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + certInfo.get(X509CertInfo.SUBJECT), "" } + ); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", e.toString())); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", e.toString())); + } + return; + } + // if service error use standard error templates. + Integer result = req.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(req.getExtDataInString(IRequest.ERROR)); + String[] svcErrors = + req.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + //System.out.println( + //"revocation servlet: setting error description "+ + //err.toString()); + cmsReq.setErrorDescription(err); + // audit log the error + try { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + "completed with error: " + + err, + certInfo.get(X509CertInfo.SUBJECT), "" } + ); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", + e.toString())); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_GET_CERT_SUBJ_AUDITING", + e.toString())); + } + } + } + } + return; + } + + // service success + cmsReq.setStatus(CMSRequest.SUCCESS); + X509CertImpl[] issuedCerts = + req.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + // audit log the success. + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + "completed", + issuedCerts[0].getSubjectDN(), + "cert issued serial number: 0x" + + issuedCerts[0].getSerialNumber().toString(16) } + ); + + // return cert as mime type binary if requested. + if (checkImportCertToNav( + cmsReq.getHttpResp(), httpParams, issuedCerts[0])) { + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + // use success template. + try { + cmsReq.setResult(issuedCerts); + renderTemplate(cmsReq, mEnrollSuccessTemplate, + mEnrollSuccessFiller); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_TEMP_REND_ERR", mEnrollSuccessFiller.toString(), e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_RETURNING_RESULT_ERROR")); + } + return; + } + + /** + * fill subject name, validity, extensions from authoken if any, + * overriding what was in pkcs10. + * fill subject name, extensions from http input if not authenticated. + * requests not authenticated will need to be approved by an agent. + */ + protected void fillCertInfoFromAuthToken( + X509CertInfo certInfo, IAuthToken authToken) + throws EBaseException { + // override subject, validity and extensions from auth token + // CA determines algorithm, version and issuer. + // take key from keygen, cmc, pkcs10 or crmf. + + // subject name. + try { + String subjectname = + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT); + + if (subjectname != null) { + CertificateSubjectName certSubject = (CertificateSubjectName) + new CertificateSubjectName(new X500Name(subjectname)); + + certInfo.set(X509CertInfo.SUBJECT, certSubject); + log(ILogger.LL_INFO, + "cert subject set to " + certSubject + " from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } + + // validity + try { + CertificateValidity validity = null; + Date notBefore = + authToken.getInDate(AuthToken.TOKEN_CERT_NOTBEFORE); + Date notAfter = + authToken.getInDate(AuthToken.TOKEN_CERT_NOTAFTER); + + if (notBefore != null && notAfter != null) { + validity = new CertificateValidity(notBefore, notAfter); + certInfo.set(X509CertInfo.VALIDITY, validity); + log(ILogger.LL_INFO, + "cert validity set to " + validity + " from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR")); + } + + // extensions + try { + CertificateExtensions extensions = + authToken.getInCertExts(X509CertInfo.EXTENSIONS); + + if (extensions != null) { + certInfo.set(X509CertInfo.EXTENSIONS, extensions); + log(ILogger.LL_INFO, "cert extensions set from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR")); + } + } + + protected X509CertInfo[] fillCRMF( + String crmf, IAuthToken authToken, IArgBlock httpParams, IRequest req) + throws EBaseException { + try { + byte[] crmfBlob = CMS.AtoB(crmf); + ByteArrayInputStream crmfBlobIn = + new ByteArrayInputStream(crmfBlob); + + SEQUENCE crmfMsgs = (SEQUENCE) + new SEQUENCE.OF_Template(new CertReqMsg.Template()).decode(crmfBlobIn); + + int nummsgs = crmfMsgs.size(); + X509CertInfo[] certInfoArray = new X509CertInfo[nummsgs]; + + for (int i = 0; i < nummsgs; i++) { + // decode message. + CertReqMsg certReqMsg = (CertReqMsg) crmfMsgs.elementAt(i); + + /* + if (certReqMsg.hasPop()) { + try { + certReqMsg.verify(); + } catch (ChallengeResponseException ex) { + // create and save the challenge + // construct the cmmf message together + // in a sequence to challenge the requestor + } catch (Exception e) { + // failed, should only affect one request + } + } + */ + CertRequest certReq = certReqMsg.getCertReq(); + INTEGER certReqId = certReq.getCertReqId(); + int srcId = certReqId.intValue(); + + req.setExtData(IRequest.CRMF_REQID, String.valueOf(srcId)); + + CertTemplate certTemplate = certReq.getCertTemplate(); + X509CertInfo certInfo = CMS.getDefaultX509CertInfo(); + + // get key + SubjectPublicKeyInfo spki = certTemplate.getPublicKey(); + ByteArrayOutputStream keyout = new ByteArrayOutputStream(); + + spki.encode(keyout); + byte[] keybytes = keyout.toByteArray(); + X509Key key = new X509Key(); + + key.decode(keybytes); + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + + // field suggested notBefore and notAfter in CRMF + // Tech Support #383184 + if (certTemplate.getNotBefore() != null || certTemplate.getNotAfter() != null) { + CertificateValidity certValidity = + new CertificateValidity(certTemplate.getNotBefore(), certTemplate.getNotAfter()); + + certInfo.set(X509CertInfo.VALIDITY, certValidity); + } + + if (certTemplate.hasSubject()) { + Name subjectdn = certTemplate.getSubject(); + ByteArrayOutputStream subjectEncStream = + new ByteArrayOutputStream(); + + subjectdn.encode(subjectEncStream); + byte[] subjectEnc = subjectEncStream.toByteArray(); + X500Name subject = new X500Name(subjectEnc); + + certInfo.set(X509CertInfo.SUBJECT, + new CertificateSubjectName(subject)); + } else if (authToken == null || + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) { + // No subject name - error! + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + } + + // get extensions + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) + certInfo.get(X509CertInfo.EXTENSIONS); + } catch (CertificateException e) { + extensions = null; + } catch (IOException e) { + extensions = null; + } + if (certTemplate.hasExtensions()) { + // put each extension from CRMF into CertInfo. + // index by extension name, consistent with + // CertificateExtensions.parseExtension() method. + if (extensions == null) + extensions = new CertificateExtensions(); + int numexts = certTemplate.numExtensions(); + + for (int j = 0; j < numexts; j++) { + org.mozilla.jss.pkix.cert.Extension jssext = + certTemplate.extensionAt(j); + boolean isCritical = jssext.getCritical(); + org.mozilla.jss.asn1.OBJECT_IDENTIFIER jssoid = + jssext.getExtnId(); + long[] numbers = jssoid.getNumbers(); + int[] oidNumbers = new int[numbers.length]; + + for (int k = numbers.length - 1; k >= 0; k--) { + oidNumbers[k] = (int) numbers[k]; + } + ObjectIdentifier oid = + new ObjectIdentifier(oidNumbers); + org.mozilla.jss.asn1.OCTET_STRING jssvalue = + jssext.getExtnValue(); + ByteArrayOutputStream jssvalueout = + new ByteArrayOutputStream(); + + jssvalue.encode(jssvalueout); + byte[] extValue = jssvalueout.toByteArray(); + + Extension ext = + new Extension(oid, isCritical, extValue); + + extensions.parseExtension(ext); + } + + certInfo.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + certInfo.set(X509CertInfo.EXTENSIONS, extensions); + + } + + // Added a new configuration parameter + // eeGateway.Enrollment.authTokenOverride=[true|false] + // By default, it is set to true. In most + // of the case, administrator would want + // to have the control of the subject name + // formulation. + // -- CRMFfillCert + if (authToken != null && + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null) { + // if authenticated override subect name, validity and + // extensions if any from authtoken. + fillCertInfoFromAuthToken(certInfo, authToken); + } + + certInfoArray[i] = certInfo; + } + + do_testbed_hack(nummsgs, certInfoArray, httpParams); + + return certInfoArray; + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } catch (InvalidBERException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } catch (InvalidKeyException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } + } + + protected void renderServerEnrollResult(CMSRequest cmsReq) throws + IOException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + httpResp.setContentType("text/html"); + ServletOutputStream out = null; + + out = httpResp.getOutputStream(); + + // get template based on request status + out.println("<HTML>"); + out.println("<TITLE>"); + out.println("Server Enrollment"); + out.println("</TITLE>"); + // out.println("<BODY BGCOLOR=white>"); + + if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.COMPLETE)) { + out.println("<H1>"); + out.println("SUCCESS"); + out.println("</H1>"); + out.println("Your request is submitted and approved. Please cut and paste the certificate into your server."); // XXX - localize the message + out.println("<P>"); + out.println("Request Creation Time: "); + out.println(cmsReq.getIRequest().getCreationTime().toString()); + out.println("<P>"); + out.println("Request Status: "); + out.println(cmsReq.getStatus().toString()); + out.println("<P>"); + out.println("Request ID: "); + out.println(cmsReq.getIRequest().getRequestId().toString()); + out.println("<P>"); + out.println("Certificate: "); + out.println("<P>"); + out.println("<PRE>"); + X509CertImpl certs[] = + cmsReq.getIRequest().getExtDataInCertArray(IRequest.ISSUED_CERTS); + + out.println(CMS.getEncodedCert(certs[0])); + out.println("</PRE>"); + out.println("<P>"); + out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" + + cmsReq.getIRequest().getCreationTime().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_STATUS=" + + cmsReq.getStatus().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_ID=" + + cmsReq.getIRequest().getRequestId().toString() + ">"); + out.println("<!HTTP_OUTPUT X509_CERTIFICATE=" + + CMS.getEncodedCert(certs[0]) + ">"); + } else if (cmsReq.getIRequest().getRequestStatus().equals(RequestStatus.PENDING)) { + out.println("<H1>"); + out.println("PENDING"); + out.println("</H1>"); + out.println("Your request is submitted. You can check on the status of your request with an authorized agent or local administrator by referring to the request ID."); // XXX - localize the message + out.println("<P>"); + out.println("Request Creation Time: "); + out.println(cmsReq.getIRequest().getCreationTime().toString()); + out.println("<P>"); + out.println("Request Status: "); + out.println(cmsReq.getStatus().toString()); + out.println("<P>"); + out.println("Request ID: "); + out.println(cmsReq.getIRequest().getRequestId().toString()); + out.println("<P>"); + out.println("<!HTTP_OUTPUT REQUEST_CREATION_TIME=" + + cmsReq.getIRequest().getCreationTime().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_STATUS=" + + cmsReq.getStatus().toString() + ">"); + out.println("<!HTTP_OUTPUT REQUEST_ID=" + + cmsReq.getIRequest().getRequestId().toString() + ">"); + } else { + out.println("<H1>"); + out.println("ERROR"); + out.println("</H1>"); + out.println("<!INFO>"); + out.println("Please consult your local administrator for assistance."); // XXX - localize the message + out.println("<!/INFO>"); + out.println("<P>"); + out.println("Request Status: "); + out.println(cmsReq.getStatus().toString()); + out.println("<P>"); + out.println("Error: "); + out.println(cmsReq.getError()); // XXX - need to parse in Locale + out.println("<P>"); + out.println("<!HTTP_OUTPUT REQUEST_STATUS=" + + cmsReq.getStatus().toString() + ">"); + out.println("<!HTTP_OUTPUT ERROR=" + + cmsReq.getError() + ">"); + } + + /** + * // include all the input data + * IArgBlock args = cmsReq.getHttpParams(); + * Enumeration ele = args.getElements(); + * while (ele.hasMoreElements()) { + * String eleT = (String)ele.nextElement(); + * out.println("<!HTTP_INPUT " + eleT + "=" + + * args.get(eleT) + ">"); + * } + **/ + + out.println("</HTML>"); + } + + // XXX ALERT !! + // Remove the following and calls to them when we bundle a cartman + // later than alpha1. + // These are here to cover up problem in cartman where the + // key usage extension always ends up being digital signature only + // and for rsa-ex ends up having no bits set. + + private boolean mIsTestBed = false; + + private void init_testbed_hack(IConfigStore config) + throws EBaseException { + mIsTestBed = config.getBoolean("isTestBed", true); + } + + private void do_testbed_hack( + int nummsgs, X509CertInfo[] certinfo, IArgBlock httpParams) + throws EBaseException { + if (!mIsTestBed) + return; + + // get around bug in cartman - bits are off by one byte. + for (int i = 0; i < certinfo.length; i++) { + try { + X509CertInfo cert = certinfo[i]; + CertificateExtensions exts = (CertificateExtensions) + cert.get(CertificateExtensions.NAME); + + if (exts == null) { + // should not happen. + continue; + } + KeyUsageExtension ext = (KeyUsageExtension) + exts.get(KeyUsageExtension.NAME); + + if (ext == null) + // should not happen + continue; + byte[] value = ext.getExtensionValue(); + + if (value[0] == 0x03 && value[1] == 0x02 && value[2] == 0x07) { + byte[] newvalue = new byte[value.length + 1]; + + newvalue[0] = 0x03; + newvalue[1] = 0x03; + newvalue[2] = 0x07; + newvalue[3] = value[3]; + // force encryption certs to have digitial signature + // set too so smime can find the cert for encryption. + if (value[3] == 0x20) { + + /* + newvalue[3] = 0x3f; + newvalue[4] = (byte)0x80; + */ + if (httpParams.getValueAsBoolean( + "dual-use-hack", true)) { + newvalue[3] = (byte) 0xE0; // same as rsa-dual-use. + } + } + newvalue[4] = 0; + KeyUsageExtension newext = + new KeyUsageExtension(Boolean.valueOf(true), + (Object) newvalue); + + exts.delete(KeyUsageExtension.NAME); + exts.set(KeyUsageExtension.NAME, newext); + } + } catch (IOException e) { + // should never happen + continue; + } catch (CertificateException e) { + // should never happen + continue; + } + } + + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java new file mode 100644 index 000000000..2f551d3f5 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java @@ -0,0 +1,381 @@ +// --- 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.cert; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.pkcs.ContentInfo; +import netscape.security.pkcs.PKCS7; +import netscape.security.pkcs.SignerInfo; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.X509CertImpl; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.cmmf.CertOrEncCert; +import org.mozilla.jss.pkix.cmmf.CertRepContent; +import org.mozilla.jss.pkix.cmmf.CertResponse; +import org.mozilla.jss.pkix.cmmf.CertifiedKeyPair; +import org.mozilla.jss.pkix.cmmf.PKIStatusInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.ICertPrettyPrint; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.util.Utils; + +/** + * Set up HTTP response to import certificate into browsers + * + * The result must have been populate with the set of certificates + * to return. + * + * <pre> + * inputs: certtype. + * outputs: + * - cert type from http input (if any) + * - CA chain + * - authority name (RM, CM, DRM) + * - scheme:host:port of server. + * array of one or more + * - cert serial number + * - cert pretty print + * - cert in base 64 encoding. + * - cmmf blob to import + * </pre> + * + * @version $Revision$, $Date$ + */ +public class ImportCertsTemplateFiller implements ICMSTemplateFiller { + public static final String CRMF_REQID = "crmfReqId"; + public static final String ISSUED_CERT_SERIAL = "serialNo"; + public static final String CERT_TYPE = "certType"; + public static final String BASE64_CERT = "base64Cert"; + public static final String CERT_PRETTYPRINT = "certPrettyPrint"; + public static final String CERT_FINGERPRINT = "certFingerprint"; // cisco + public static final String CERT_NICKNAME = "certNickname"; + public static final String CMMF_RESP = "cmmfResponse"; + public static final String PKCS7_RESP = "pkcs7ChainBase64"; // for MSIE + + public ImportCertsTemplateFiller() { + } + + /** + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) + throws Exception { + Certificate[] certs = (Certificate[]) cmsReq.getResult(); + + if (certs instanceof X509CertImpl[]) + return getX509TemplateParams(cmsReq, authority, locale, e); + else + return null; + } + + public CMSTemplateParams getX509TemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) + throws Exception { + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(header, fixed); + + // set host name and port. + HttpServletRequest httpReq = cmsReq.getHttpReq(); + String host = httpReq.getServerName(); + int port = httpReq.getServerPort(); + String scheme = httpReq.getScheme(); + String format = httpReq.getParameter("format"); + if (format != null && format.equals("cmc")) + fixed.set("importCMC", "false"); + String agentPort = "" + port; + fixed.set("agentHost", host); + fixed.set("agentPort", agentPort); + fixed.set(ICMSTemplateFiller.HOST, host); + fixed.set(ICMSTemplateFiller.PORT, Integer.valueOf(port)); + fixed.set(ICMSTemplateFiller.SCHEME, scheme); + IRequest r = cmsReq.getIRequest(); + + if (r != null) { + fixed.set(ICMSTemplateFiller.REQUEST_ID, r.getRequestId().toString()); + } + + // set key record (if KRA enabled) + if (r != null) { + BigInteger keyRecSerialNo = r.getExtDataInBigInteger("keyRecord"); + + if (keyRecSerialNo != null) { + fixed.set(ICMSTemplateFiller.KEYREC_ID, keyRecSerialNo.toString()); + } + } + + // set cert type. + IArgBlock httpParams = cmsReq.getHttpParams(); + String certType = + httpParams.getValueAsString(CERT_TYPE, null); + + if (certType != null) + fixed.set(CERT_TYPE, certType); + + // this authority + fixed.set(ICMSTemplateFiller.AUTHORITY, + (String) authority.getOfficialName()); + + // CA chain. + CertificateChain cachain = + ((ICertAuthority) authority).getCACertChain(); + X509Certificate[] cacerts = cachain.getChain(); + + String replyTo = httpParams.getValueAsString("replyTo", null); + + if (replyTo != null) + fixed.set("replyTo", replyTo); + + // set user + CA cert chain and pkcs7 for MSIE. + X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1]; + int m = 1, n = 0; + + for (; n < cacerts.length; m++, n++) + userChain[m] = (X509CertImpl) cacerts[n]; + + // certs. + X509CertImpl[] certs = (X509CertImpl[]) cmsReq.getResult(); + + // expose CRMF request id + String crmfReqId = cmsReq.getExtData(IRequest.CRMF_REQID); + + if (crmfReqId == null) { + crmfReqId = (String) cmsReq.getResult( + IRequest.CRMF_REQID); + } + if (crmfReqId != null) { + fixed.set(CRMF_REQID, crmfReqId); + } + + // set CA certs in cmmf, initialize CertRepContent + // note cartman can't trust ca certs yet but it'll import them. + // also set cert nickname for cartman. + CertRepContent certRepContent = null; + + if (CMSServlet.doCMMFResponse(httpParams)) { + byte[][] caPubs = new byte[cacerts.length][]; + + for (int j = 0; j < cacerts.length; j++) + caPubs[j] = ((X509CertImpl) cacerts[j]).getEncoded(); + certRepContent = new CertRepContent(caPubs); + + String certnickname = + cmsReq.getHttpParams().getValueAsString(CERT_NICKNAME, null); + + // if nickname is not requested set to subject name by default. + if (certnickname == null) + fixed.set(CERT_NICKNAME, certs[0].getSubjectDN().toString()); + else + fixed.set(CERT_NICKNAME, certnickname); + } + + // make pkcs7 for MSIE + if (CMSServlet.clientIsMSIE(cmsReq.getHttpReq()) && + (certType == null || certType.equals("client"))) { + userChain[0] = certs[0]; + PKCS7 p7 = new PKCS7(new AlgorithmId[0], + new ContentInfo(new byte[0]), + userChain, + new SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + p7.encodeSignedData(bos); + byte[] p7Bytes = bos.toByteArray(); + // String p7Str = encoder.encodeBuffer(p7Bytes); + String p7Str = CMS.BtoA(p7Bytes); + + header.set(PKCS7_RESP, p7Str); + } + + // set base 64, pretty print and cmmf response for each issued cert. + for (int i = 0; i < certs.length; i++) { + IArgBlock repeat = CMS.createArgBlock(); + X509CertImpl cert = certs[i]; + + // set serial number. + BigInteger serialNo = + ((X509Certificate) cert).getSerialNumber(); + + repeat.addBigIntegerValue(ISSUED_CERT_SERIAL, serialNo, 16); + + // set base64 encoded blob. + byte[] certEncoded = cert.getEncoded(); + // String b64 = encoder.encodeBuffer(certEncoded); + String b64 = CMS.BtoA(certEncoded); + String b64cert = "-----BEGIN CERTIFICATE-----\n" + + b64 + "\n-----END CERTIFICATE-----"; + + repeat.set(BASE64_CERT, b64cert); + + // set cert pretty print. + + String prettyPrintRequested = + cmsReq.getHttpParams().getValueAsString(CERT_PRETTYPRINT, null); + + if (prettyPrintRequested == null) { + prettyPrintRequested = "true"; + } + String ppStr = ""; + + if (!prettyPrintRequested.equals("false")) { + ICertPrettyPrint pp = CMS.getCertPrettyPrint(cert); + + ppStr = pp.toString(locale); + } + repeat.set(CERT_PRETTYPRINT, ppStr); + + // Now formulate a PKCS#7 blob + X509CertImpl[] certsInChain = new X509CertImpl[1]; + ; + if (cacerts != null) { + for (int j = 0; j < cacerts.length; j++) { + if (cert.equals(cacerts[j])) { + certsInChain = new + X509CertImpl[cacerts.length]; + break; + } + certsInChain = new X509CertImpl[cacerts.length + 1]; + } + } + + // Set the EE cert + certsInChain[0] = cert; + + // Set the Ca certificate chain + if (cacerts != null) { + for (int j = 0; j < cacerts.length; j++) { + if (!cert.equals(cacerts[j])) + certsInChain[j + 1] = (X509CertImpl) cacerts[j]; + } + } + // Wrap the chain into a degenerate P7 object + String p7Str; + + try { + PKCS7 p7 = new PKCS7(new AlgorithmId[0], + new ContentInfo(new byte[0]), + certsInChain, + new SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + p7.encodeSignedData(bos); + byte[] p7Bytes = bos.toByteArray(); + + //p7Str = encoder.encodeBuffer(p7Bytes); + p7Str = CMS.BtoA(p7Bytes); + repeat.addStringValue("pkcs7ChainBase64", p7Str); + } catch (Exception ex) { + //p7Str = "PKCS#7 B64 Encoding error - " + ex.toString() + //+ "; Please contact your administrator"; + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_FORMING_PKCS7_ERROR")); + } + + // set cert fingerprint (for Cisco routers) + String fingerprint = null; + + try { + fingerprint = CMS.getFingerPrints(cert); + } catch (CertificateEncodingException ex) { + // should never happen + throw new EBaseException( + CMS.getUserMessage(locale, "CMS_BASE_INTERNAL_ERROR", ex.toString())); + } catch (NoSuchAlgorithmException ex) { + // should never happen + throw new EBaseException( + CMS.getUserMessage(locale, "CMS_BASE_INTERNAL_ERROR", ex.toString())); + } + if (fingerprint != null && fingerprint.length() > 0) + repeat.set(CERT_FINGERPRINT, fingerprint); + + // cmmf response for this cert. + if (CMSServlet.doCMMFResponse(httpParams) && crmfReqId != null && + (certType == null || certType.equals("client"))) { + PKIStatusInfo status = new PKIStatusInfo(PKIStatusInfo.granted); + CertifiedKeyPair certifiedKP = + new CertifiedKeyPair(new CertOrEncCert(certEncoded)); + CertResponse resp = + new CertResponse(new INTEGER(crmfReqId), status, + certifiedKP); + + certRepContent.addCertResponse(resp); + } + + params.addRepeatRecord(repeat); + } + + // if cartman set whole cmmf response (CertRepContent) string. + if (CMSServlet.doCMMFResponse(httpParams)) { + ByteArrayOutputStream certRepOut = new ByteArrayOutputStream(); + + certRepContent.encode(certRepOut); + byte[] certRepBytes = certRepOut.toByteArray(); + String certRepB64 = Utils.base64encode(certRepBytes); + // add CR to each return as required by cartman + BufferedReader certRepB64lines = + new BufferedReader(new StringReader(certRepB64)); + StringWriter certRepStringOut = new StringWriter(); + String oneLine = null; + boolean first = true; + + while ((oneLine = certRepB64lines.readLine()) != null) { + if (first) { + //certRepStringOut.write("\""+oneLine+"\""); + certRepStringOut.write(oneLine); + first = false; + } else { + //certRepStringOut.write("+\"\\n"+oneLine+"\""); + certRepStringOut.write("\n" + oneLine); + } + } + String certRepString = certRepStringOut.toString(); + + fixed.set(CMMF_RESP, certRepString); + } + + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/ListCerts.java b/base/common/src/com/netscape/cms/servlet/cert/ListCerts.java new file mode 100644 index 000000000..b93a82fb8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/ListCerts.java @@ -0,0 +1,672 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.PublicKey; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.provider.RSAPublicKey; +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertRecordList; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.dbs.certdb.IRevocationInfo; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve a paged list of certs matching the specified query + * + * @version $Revision$, $Date$ + */ +public class ListCerts extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -3568155814023099576L; + private final static String TPL_FILE = "queryCert.template"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + + private final static String USE_CLIENT_FILTER = "useClientFilter"; + private final static String ALLOWED_CLIENT_FILTERS = "allowedClientFilters"; + + private ICertificateRepository mCertDB = null; + private X500Name mAuthName = null; + private String mFormPath = null; + private boolean mReverse = false; + private boolean mHardJumpTo = false; //jump to the end + private String mDirection = null; + private boolean mUseClientFilter = false; + private Vector<String> mAllowedClientFilters = new Vector<String>(); + private int mMaxReturns = 2000; + + /** + * Constructs query key servlet. + */ + public ListCerts() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "queryCert.template" to render the response + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to render own template. + mTemplates.remove(CMSRequest.SUCCESS); + + if (mAuthority instanceof ICertificateAuthority) { + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + + mCertDB = ca.getCertificateRepository(); + mAuthName = ca.getX500Name(); + } + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + try { + mMaxReturns = Integer.parseInt(sc.getInitParameter("maxResults")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + + /* useClientFilter should be off by default. We keep + this parameter around so that we do not break + the client applications that submits raw LDAP + filter into this servlet. */ + if (sc.getInitParameter(USE_CLIENT_FILTER) != null && + sc.getInitParameter(USE_CLIENT_FILTER).equalsIgnoreCase("true")) { + mUseClientFilter = true; + } + if (sc.getInitParameter(ALLOWED_CLIENT_FILTERS) == null + || sc.getInitParameter(ALLOWED_CLIENT_FILTERS).equals("")) { + mAllowedClientFilters.addElement("(certStatus=*)"); + mAllowedClientFilters.addElement("(certStatus=VALID)"); + mAllowedClientFilters.addElement("(|(certStatus=VALID)(certStatus=INVALID)(certStatus=EXPIRED))"); + mAllowedClientFilters.addElement("(|(certStatus=VALID)(certStatus=REVOKED))"); + } else { + StringTokenizer st = new StringTokenizer(sc.getInitParameter(ALLOWED_CLIENT_FILTERS), ","); + while (st.hasMoreTokens()) { + mAllowedClientFilters.addElement(st.nextToken()); + } + } + } + + public String buildFilter(HttpServletRequest req) { + String queryCertFilter = req.getParameter("queryCertFilter"); + + com.netscape.certsrv.apps.CMS.debug("client queryCertFilter=" + queryCertFilter); + + if (mUseClientFilter) { + com.netscape.certsrv.apps.CMS.debug("useClientFilter=true"); + Enumeration<String> filters = mAllowedClientFilters.elements(); + // check to see if the filter is allowed + while (filters.hasMoreElements()) { + String filter = (String) filters.nextElement(); + com.netscape.certsrv.apps.CMS.debug("Comparing filter=" + + filter + " queryCertFilter=" + queryCertFilter); + if (filter.equals(queryCertFilter)) { + return queryCertFilter; + } + } + com.netscape.certsrv.apps.CMS.debug("Requested filter '" + + queryCertFilter + "' is not allowed. Please check the " + ALLOWED_CLIENT_FILTERS + "parameter"); + return null; + } else { + com.netscape.certsrv.apps.CMS.debug("useClientFilter=false"); + } + + boolean skipRevoked = false; + boolean skipNonValid = false; + if (req.getParameter("skipRevoked") != null && + req.getParameter("skipRevoked").equals("on")) { + skipRevoked = true; + } + if (req.getParameter("skipNonValid") != null && + req.getParameter("skipNonValid").equals("on")) { + skipNonValid = true; + } + + if (!skipRevoked && !skipNonValid) { + queryCertFilter = "(certStatus=*)"; + } else if (skipRevoked && skipNonValid) { + queryCertFilter = "(certStatus=VALID)"; + } else if (skipRevoked) { + queryCertFilter = "(|(certStatus=VALID)(certStatus=INVALID)(certStatus=EXPIRED))"; + } else if (skipNonValid) { + queryCertFilter = "(|(certStatus=VALID)(certStatus=REVOKED))"; + } + return queryCertFilter; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param maxCount Number of certificates to show + * <li>http.param queryFilter and ldap style filter specifying the certificates to show + * <li>http.param querySentinelDown the serial number of the first certificate to show (default decimal, or hex if + * prefixed with 0x) when paging down + * <li>http.param querySentinelUp the serial number of the first certificate to show (default decimal, or hex if + * prefixed with 0x) when paging up + * <li>http.param direction "up", "down", "begin", or "end" + * </ul> + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "list"); + } catch (Exception e) { + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String revokeAll = null; + EBaseException error = null; + + int maxCount = -1; + BigInteger sentinel = new BigInteger("0"); + + IArgBlock header = com.netscape.certsrv.apps.CMS.createArgBlock(); + IArgBlock ctx = com.netscape.certsrv.apps.CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + com.netscape.certsrv.apps.CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + com.netscape.certsrv.apps.CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + mHardJumpTo = false; + try { + + if (req.getParameter("direction") != null) { + mDirection = req.getParameter("direction").trim(); + mReverse = mDirection.equals("up"); + if (mReverse) + com.netscape.certsrv.apps.CMS.debug("reverse is true"); + else + com.netscape.certsrv.apps.CMS.debug("reverse is false"); + + } + + if (req.getParameter("maxCount") != null) { + maxCount = Integer.parseInt(req.getParameter("maxCount")); + } + if (maxCount == -1 || maxCount > mMaxReturns) { + com.netscape.certsrv.apps.CMS.debug("Resetting page size from " + maxCount + " to " + mMaxReturns); + maxCount = mMaxReturns; + } + + String sentinelStr = ""; + if (mReverse) { + sentinelStr = req.getParameter("querySentinelUp"); + } else if (mDirection.equals("end")) { + // this servlet will figure out the end + sentinelStr = "0"; + mReverse = true; + mHardJumpTo = true; + } else if (mDirection.equals("down")) { + sentinelStr = req.getParameter("querySentinelDown"); + } else + sentinelStr = "0"; + //begin and non-specified have sentinel default "0" + + if (sentinelStr != null) { + if (sentinelStr.trim().startsWith("0x")) { + sentinel = new BigInteger(sentinelStr.trim().substring(2), 16); + } else { + sentinel = new BigInteger(sentinelStr, 10); + } + } + + revokeAll = req.getParameter("revokeAll"); + + if (mAuthority instanceof ICertificateAuthority) { + X509CertImpl caCert = ((ICertificateAuthority) mAuthority).getSigningUnit().getCertImpl(); + + //if (isCertFromCA(caCert)) + header.addStringValue("caSerialNumber", + caCert.getSerialNumber().toString(16)); + } + + // constructs the ldap filter on the server side + String queryCertFilter = buildFilter(req); + + if (queryCertFilter == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + com.netscape.certsrv.apps.CMS.debug("queryCertFilter=" + queryCertFilter); + + int totalRecordCount = -1; + + try { + totalRecordCount = Integer.parseInt(req.getParameter("totalRecordCount")); + } catch (Exception e) { + } + processCertFilter(argSet, header, maxCount, + sentinel, + totalRecordCount, + req.getParameter("serialTo"), + queryCertFilter, + req, resp, revokeAll, locale[0]); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, com.netscape.certsrv.apps.CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + + error = + new EBaseException(com.netscape.certsrv.apps.CMS.getUserMessage(getLocale(req), + "CMS_BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } + + ctx.addIntegerValue("maxCount", maxCount); + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + cmsReq.setStatus(CMSRequest.SUCCESS); + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + com.netscape.certsrv.apps.CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + com.netscape.certsrv.apps.CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + private void processCertFilter(CMSTemplateParams argSet, + IArgBlock header, + int maxCount, + BigInteger sentinel, + int totalRecordCount, + String serialTo, + String filter, + HttpServletRequest req, + HttpServletResponse resp, + String revokeAll, + Locale locale + ) throws EBaseException { + BigInteger serialToVal = MINUS_ONE; + + try { + if (serialTo != null) { + serialTo = serialTo.trim(); + if (serialTo.startsWith("0x")) { + serialToVal = new BigInteger + (serialTo.substring(2), 16); + serialTo = serialToVal.toString(); + } else { + serialToVal = new BigInteger(serialTo); + } + } + } catch (Exception e) { + } + + String jumpTo = sentinel.toString(); + int pSize = 0; + if (mReverse) { + if (!mHardJumpTo) //reverse gets one more + pSize = -1 * maxCount - 1; + else + pSize = -1 * maxCount; + } else + pSize = maxCount; + + ICertRecordList list = (ICertRecordList) mCertDB.findCertRecordsInList( + filter, (String[]) null, jumpTo, mHardJumpTo, "serialno", + pSize); + // retrive maxCount + 1 entries + + Enumeration<ICertRecord> e = list.getCertRecords(0, maxCount); + + ICertRecordList tolist = null; + int toCurIndex = 0; + + if (!serialToVal.equals(MINUS_ONE)) { + // if user specify a range, we need to + // calculate the totalRecordCount + tolist = (ICertRecordList) mCertDB.findCertRecordsInList( + filter, + (String[]) null, serialTo, + "serialno", maxCount); + Enumeration<ICertRecord> en = tolist.getCertRecords(0, 0); + + if (en == null || (!en.hasMoreElements())) { + toCurIndex = list.getSize() - 1; + } else { + toCurIndex = tolist.getCurrentIndex(); + ICertRecord rx = en.nextElement(); + BigInteger curToSerial = rx.getSerialNumber(); + + if (curToSerial.compareTo(serialToVal) == -1) { + toCurIndex = list.getSize() - 1; + } else { + if (!rx.getSerialNumber().toString().equals(serialTo.trim())) { + toCurIndex = toCurIndex - 1; + } + } + } + } + + int curIndex = list.getCurrentIndex(); + + int count = 0; + BigInteger firstSerial = new BigInteger("0"); + BigInteger curSerial = new BigInteger("0"); + ICertRecord[] recs = new ICertRecord[maxCount]; + int rcount = 0; + + if (e != null) { + /* in reverse (page up), because the sentinel is the one after the + * last item to be displayed, we need to skip it + */ + while ((count < ((mReverse && !mHardJumpTo) ? (maxCount + 1) : maxCount)) && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) e.nextElement(); + + if (rec == null) { + com.netscape.certsrv.apps.CMS.debug("record " + count + " is null"); + break; + } + curSerial = rec.getSerialNumber(); + com.netscape.certsrv.apps.CMS.debug("record " + count + " is serial#" + curSerial); + + if (count == 0) { + firstSerial = curSerial; + if (mReverse && !mHardJumpTo) {//reverse got one more, skip + count++; + continue; + } + } + + // DS has a problem where last record will be returned + // even though the filter is not matched. + /*cfu - is this necessary? it breaks when paging up + if (curSerial.compareTo(sentinel) == -1) { + com.netscape.certsrv.apps.CMS.debug("curSerial compare sentinel -1 break..."); + + break; + } + */ + if (!serialToVal.equals(MINUS_ONE)) { + // check if we go over the limit + if (curSerial.compareTo(serialToVal) == 1) { + com.netscape.certsrv.apps.CMS.debug("curSerial compare serialToVal 1 breaking..."); + break; + } + } + + if (mReverse) { + recs[rcount++] = rec; + } else { + + IArgBlock rarg = com.netscape.certsrv.apps.CMS.createArgBlock(); + + fillRecordIntoArg(rec, rarg); + argSet.addRepeatRecord(rarg); + } + count++; + } + } else { + com.netscape.certsrv.apps.CMS.debug( + "ListCerts::processCertFilter() - no Cert Records found!"); + return; + } + + if (mReverse) { + // fill records into arg block and argSet + for (int ii = rcount - 1; ii >= 0; ii--) { + if (recs[ii] != null) { + IArgBlock rarg = com.netscape.certsrv.apps.CMS.createArgBlock(); + //com.netscape.certsrv.apps.CMS.debug("item "+ii+" is serial # "+ recs[ii].getSerialNumber()); + fillRecordIntoArg(recs[ii], rarg); + argSet.addRepeatRecord(rarg); + } + } + } + + // peek ahead + ICertRecord nextRec = null; + + if (e.hasMoreElements()) { + nextRec = (ICertRecord) e.nextElement(); + } + + header.addStringValue("op", req.getParameter("op")); + if (revokeAll != null) + header.addStringValue("revokeAll", revokeAll); + if (mAuthName != null) + header.addStringValue("issuerName", mAuthName.toString()); + if (!serialToVal.equals(MINUS_ONE)) + header.addStringValue("serialTo", serialToVal.toString()); + header.addStringValue("serviceURL", req.getRequestURI()); + header.addStringValue("queryCertFilter", filter); + header.addStringValue("templateName", "queryCert"); + header.addStringValue("queryFilter", filter); + header.addIntegerValue("maxCount", maxCount); + if (totalRecordCount == -1) { + if (!serialToVal.equals(MINUS_ONE)) { + totalRecordCount = toCurIndex - curIndex + 1; + com.netscape.certsrv.apps.CMS.debug("totalRecordCount=" + totalRecordCount); + } else { + totalRecordCount = list.getSize() - + list.getCurrentIndex(); + com.netscape.certsrv.apps.CMS.debug("totalRecordCount=" + totalRecordCount); + } + } + + header.addIntegerValue("totalRecordCount", totalRecordCount); + header.addIntegerValue("currentRecordCount", list.getSize() - + list.getCurrentIndex()); + + String qs = ""; + if (mReverse) + qs = "querySentinelUp"; + else + qs = "querySentinelDown"; + + if (mHardJumpTo) { + com.netscape.certsrv.apps.CMS.debug("curSerial added to querySentinelUp:" + curSerial.toString()); + + header.addStringValue("querySentinelUp", curSerial.toString()); + } else { + if (nextRec == null) { + header.addStringValue(qs, null); + com.netscape.certsrv.apps.CMS.debug("nextRec is null"); + if (mReverse) { + com.netscape.certsrv.apps.CMS.debug("curSerial added to querySentinelUp:" + curSerial.toString()); + + header.addStringValue("querySentinelUp", curSerial.toString()); + } + } else { + BigInteger nextRecNo = nextRec.getSerialNumber(); + + if (serialToVal.equals(MINUS_ONE)) { + header.addStringValue( + qs, nextRecNo.toString()); + } else { + if (nextRecNo.compareTo(serialToVal) <= 0) { + header.addStringValue( + qs, nextRecNo.toString()); + } else { + header.addStringValue(qs, + null); + } + } + com.netscape.certsrv.apps.CMS.debug("querySentinel " + qs + " = " + nextRecNo.toString()); + } + } // !mHardJumpto + + header.addStringValue(!mReverse ? "querySentinelUp" : "querySentinelDown", + firstSerial.toString()); + + } + + /** + * Fills cert record into argument block. + */ + private void fillRecordIntoArg(ICertRecord rec, IArgBlock rarg) + throws EBaseException { + + X509CertImpl xcert = rec.getCertificate(); + + if (xcert != null) { + fillX509RecordIntoArg(rec, rarg); + } + } + + private void fillX509RecordIntoArg(ICertRecord rec, IArgBlock rarg) + throws EBaseException { + + X509CertImpl cert = rec.getCertificate(); + + rarg.addIntegerValue("version", cert.getVersion()); + rarg.addStringValue("serialNumber", cert.getSerialNumber().toString(16)); + rarg.addStringValue("serialNumberDecimal", cert.getSerialNumber().toString()); + + if (cert.getSubjectDN().toString().equals("")) { + rarg.addStringValue("subject", " "); + } else + rarg.addStringValue("subject", cert.getSubjectDN().toString()); + + rarg.addStringValue("type", "X.509"); + + try { + PublicKey pKey = cert.getPublicKey(); + X509Key key = null; + + if (pKey instanceof CertificateX509Key) { + CertificateX509Key certKey = (CertificateX509Key) pKey; + + key = (X509Key) certKey.get(CertificateX509Key.KEY); + } + if (pKey instanceof X509Key) { + key = (X509Key) pKey; + } + rarg.addStringValue("subjectPublicKeyAlgorithm", key.getAlgorithmId().getOID().toString()); + if (key.getAlgorithmId().toString().equalsIgnoreCase("RSA")) { + RSAPublicKey rsaKey = new RSAPublicKey(key.getEncoded()); + + rarg.addIntegerValue("subjectPublicKeyLength", rsaKey.getKeySize()); + } + } catch (Exception e) { + rarg.addStringValue("subjectPublicKeyAlgorithm", null); + rarg.addIntegerValue("subjectPublicKeyLength", 0); + } + + rarg.addLongValue("validNotBefore", cert.getNotBefore().getTime() / 1000); + rarg.addLongValue("validNotAfter", cert.getNotAfter().getTime() / 1000); + rarg.addStringValue("signatureAlgorithm", cert.getSigAlgOID()); + String issuedBy = rec.getIssuedBy(); + + if (issuedBy == null) + issuedBy = ""; + rarg.addStringValue("issuedBy", issuedBy); // cert.getIssuerDN().toString() + rarg.addLongValue("issuedOn", rec.getCreateTime().getTime() / 1000); + + rarg.addStringValue("revokedBy", + ((rec.getRevokedBy() == null) ? "" : rec.getRevokedBy())); + if (rec.getRevokedOn() == null) { + rarg.addStringValue("revokedOn", null); + } else { + rarg.addLongValue("revokedOn", rec.getRevokedOn().getTime() / 1000); + + IRevocationInfo revocationInfo = rec.getRevocationInfo(); + + if (revocationInfo != null) { + CRLExtensions crlExts = revocationInfo.getCRLEntryExtensions(); + + if (crlExts != null) { + Enumeration<Extension> enum1 = crlExts.getElements(); + int reason = 0; + + while (enum1.hasMoreElements()) { + Extension ext = (Extension) enum1.nextElement(); + + if (ext instanceof CRLReasonExtension) { + reason = ((CRLReasonExtension) ext).getReason().toInt(); + break; + } + } + rarg.addIntegerValue("revocationReason", reason); + } + } + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/Monitor.java b/base/common/src/com/netscape/cms/servlet/cert/Monitor.java new file mode 100644 index 000000000..ac531caca --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/Monitor.java @@ -0,0 +1,407 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X500Name; + +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.base.IArgBlock; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequestList; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.IRequestRecord; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Provide statistical queries of request and certificate records. + * + * @version $Revision$, $Date$ + */ +public class Monitor extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -8492837942132357692L; + private final static String TPL_FILE = "monitor.template"; + private final static String INFO = "Monitor"; + + private ICertificateRepository mCertDB = null; + private IRequestQueue mQueue = null; + private X500Name mAuthName = null; + private String mFormPath = null; + + private int mTotalCerts = 0; + private int mTotalReqs = 0; + + /** + * Constructs query servlet. + */ + public Monitor() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * 'monitor.template' to render the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to render own template. + mTemplates.remove(CMSRequest.SUCCESS); + + if (mAuthority instanceof ICertificateAuthority) { + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + + mCertDB = ca.getCertificateRepository(); + mAuthName = ca.getX500Name(); + } + mQueue = mAuthority.getRequestQueue(); + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param startTime start of time period to query + * <li>http.param endTime end of time period to query + * <li>http.param interval time between queries + * <li>http.param numberOfIntervals number of queries to run + * <li>http.param maxResults =number + * <li>http.param timeLimit =time + * </ul> + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String startTime = null; + String endTime = null; + String interval = null; + String numberOfIntervals = null; + + EBaseException error = null; + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + startTime = req.getParameter("startTime"); + endTime = req.getParameter("endTime"); + interval = req.getParameter("interval"); + numberOfIntervals = req.getParameter("numberOfIntervals"); + + process(argSet, header, startTime, endTime, interval, numberOfIntervals, locale[0]); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_PROCESSING_REQ", e.toString())); + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", + e.toString())); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + private void process(CMSTemplateParams argSet, IArgBlock header, + String startTime, String endTime, + String interval, String numberOfIntervals, + Locale locale) + throws EBaseException { + if (interval == null || interval.length() == 0) { + header.addStringValue("error", "Invalid interval: " + interval); + return; + } + if (numberOfIntervals == null || numberOfIntervals.length() == 0) { + header.addStringValue("error", "Invalid number of intervals: " + numberOfIntervals); + return; + } + + Date startDate = StringToDate(startTime); + + if (startDate == null) { + header.addStringValue("error", "Invalid start time: " + startTime); + return; + } + + int iInterval = 0; + + try { + iInterval = Integer.parseInt(interval); + } catch (NumberFormatException nfe) { + header.addStringValue("error", "Invalid interval: " + interval); + return; + } + + int iNumberOfIntervals = 0; + + try { + iNumberOfIntervals = Integer.parseInt(numberOfIntervals); + } catch (NumberFormatException nfe) { + header.addStringValue("error", "Invalid number of intervals: " + numberOfIntervals); + return; + } + + header.addStringValue("startDate", startDate.toString()); + header.addStringValue("startTime", startTime); + header.addIntegerValue("interval", iInterval); + header.addIntegerValue("numberOfIntervals", iNumberOfIntervals); + + mTotalCerts = 0; + mTotalReqs = 0; + + Date d1 = startDate; + + for (int i = 0; i < iNumberOfIntervals; i++) { + Date d2 = nextDate(d1, iInterval - 1); + IArgBlock rarg = CMS.createArgBlock(); + String e = getIntervalInfo(rarg, d1, d2); + + if (e != null) { + header.addStringValue("error", e); + return; + } + argSet.addRepeatRecord(rarg); + d1 = nextDate(d2, 1); + } + + header.addIntegerValue("totalNumberOfCertificates", mTotalCerts); + header.addIntegerValue("totalNumberOfRequests", mTotalReqs); + + if (mAuthName != null) + header.addStringValue("issuerName", mAuthName.toString()); + + return; + } + + Date nextDate(Date d, int seconds) { + Date date = new Date((d.getTime()) + ((long) (seconds * 1000))); + + return date; + } + + String getIntervalInfo(IArgBlock arg, Date startDate, Date endDate) { + if (startDate != null && endDate != null) { + String startTime = DateToZString(startDate); + String endTime = DateToZString(endDate); + String filter = null; + + arg.addStringValue("startTime", startTime); + arg.addStringValue("endTime", endTime); + + try { + if (mCertDB != null) { + filter = Filter(ICertRecord.ATTR_CREATE_TIME, startTime, endTime); + + Enumeration<Object> e = mCertDB.findCertRecs(filter); + + int count = 0; + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) e.nextElement(); + + if (rec != null) { + count++; + } + } + arg.addIntegerValue("numberOfCertificates", count); + mTotalCerts += count; + } + + if (mQueue != null) { + filter = Filter(IRequestRecord.ATTR_CREATE_TIME, startTime, endTime); + + IRequestList reqList = mQueue.listRequestsByFilter(filter); + + int count = 0; + + while (reqList != null && reqList.hasMoreElements()) { + IRequestRecord rec = (IRequestRecord) reqList.nextRequest(); + + if (rec != null) { + if (count == 0) { + arg.addStringValue("firstRequest", rec.getRequestId().toString()); + } + count++; + } + } + arg.addIntegerValue("numberOfRequests", count); + mTotalReqs += count; + } + } catch (Exception ex) { + return "Exception: " + ex; + } + + return null; + } else { + return "Missing start or end date"; + } + } + + Date StringToDate(String z) { + Date d = null; + + if (z != null && (z.length() == 14 || + z.length() == 15 && (z.charAt(14) == 'Z' || z.charAt(14) == 'z'))) { + // 20020516132030Z or 20020516132030 + try { + int year = Integer.parseInt(z.substring(0, 4)); + int month = Integer.parseInt(z.substring(4, 6)) - 1; + int date = Integer.parseInt(z.substring(6, 8)); + int hour = Integer.parseInt(z.substring(8, 10)); + int minute = Integer.parseInt(z.substring(10, 12)); + int second = Integer.parseInt(z.substring(12, 14)); + Calendar calendar = Calendar.getInstance(); + calendar.set(year, month, date, hour, minute, second); + d = calendar.getTime(); + } catch (NumberFormatException nfe) { + } + } else if (z != null && z.length() > 1 && z.charAt(0) == '-') { // -5 + try { + int i = Integer.parseInt(z); + + d = new Date(); + d = nextDate(d, i); + } catch (NumberFormatException nfe) { + } + } + + return d; + } + + String DateToZString(Date d) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(d); + + String time = "" + (calendar.get(Calendar.YEAR)); + int i = calendar.get(Calendar.MONTH) + 1; + + if (i < 10) + time += "0"; + time += i; + i = calendar.get(Calendar.DAY_OF_MONTH); + if (i < 10) + time += "0"; + time += i; + i = calendar.get(Calendar.HOUR_OF_DAY); + if (i < 10) + time += "0"; + time += i; + i = calendar.get(Calendar.MINUTE); + if (i < 10) + time += "0"; + time += i; + i = calendar.get(Calendar.SECOND); + if (i < 10) + time += "0"; + time += i + "Z"; + return time; + } + + String Filter(String name, String start, String end) { + String filter = "(&(" + name + ">=" + start + ")(" + name + "<=" + end + "))"; + + return filter; + } + + String uriFilter(String name, String start, String end) { + String filter = "(%26(" + name + "%3e%3d" + start + ")(" + name + "%3c%3d" + end + "))"; + + return filter; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java b/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java new file mode 100644 index 000000000..0f21e1921 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java @@ -0,0 +1,287 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Random; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +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.base.IArgBlock; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Specify the RevocationReason when revoking a certificate + * + * @version $Revision$, $Date$ + */ +public class ReasonToRevoke extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -8447580860330758660L; + private final static String TPL_FILE = "reasonToRevoke.template"; + private final static String INFO = "ReasonToRevoke"; + + private ICertificateRepository mCertDB = null; + private String mFormPath = null; + private ICertificateAuthority mCA = null; + private Random mRandom = null; + private Nonces mNonces = null; + private int mTimeLimits = 30; /* in seconds */ + + public ReasonToRevoke() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * 'reasonToRevoke.template' to render the response + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mAuthority instanceof ICertificateAuthority) { + mCA = (ICertificateAuthority) mAuthority; + mCertDB = ((ICertificateAuthority) mAuthority).getCertificateRepository(); + } + + if (mCA != null && mCA.noncesEnabled()) { + mRandom = new Random(); + mNonces = mCA.getNonces(); + } + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + /* Server-Side time limit */ + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "revoke"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String revokeAll = null; + int totalRecordCount = 1; + EBaseException error = null; + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + try { + if (req.getParameter("totalRecordCount") != null) { + totalRecordCount = + Integer.parseInt(req.getParameter("totalRecordCount")); + } + + revokeAll = req.getParameter("revokeAll"); + + process(argSet, header, req, resp, + revokeAll, totalRecordCount, locale[0]); + } catch (EBaseException e) { + error = e; + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_RECORD_COUNT_FORMAT")); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } + + /* + catch (Exception e) { + noError = false; + header.addStringValue(OUT_ERROR, + MessageFormatter.getLocalizedString( + errorlocale[0], + BaseResources.class.getName(), + BaseResources.INTERNAL_ERROR_1, + e.toString())); + } + */ + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + private void process(CMSTemplateParams argSet, IArgBlock header, + HttpServletRequest req, + HttpServletResponse resp, + String revokeAll, int totalRecordCount, + Locale locale) + throws EBaseException { + + header.addStringValue("revokeAll", revokeAll); + header.addIntegerValue("totalRecordCount", totalRecordCount); + + if (mNonces != null) { + long n = mRandom.nextLong(); + long m = mNonces.addNonce(n, getSSLClientCertificate(req)); + if ((n + m) != 0) { + header.addStringValue("nonce", Long.toString(m)); + } + } + + try { + if (mCA != null) { + X509CertImpl caCert = mCA.getSigningUnit().getCertImpl(); + + if (isCertFromCA(caCert)) { + header.addStringValue("caSerialNumber", + caCert.getSerialNumber().toString(16)); + } + } + + /** + * ICertRecordList list = mCertDB.findCertRecordsInList( + * revokeAll, null, totalRecordCount); + * Enumeration e = list.getCertRecords(0, totalRecordCount - 1); + **/ + Enumeration<ICertRecord> e = mCertDB.searchCertificates(revokeAll, + totalRecordCount, mTimeLimits); + + int count = 0; + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = e.nextElement(); + + if (rec == null) + continue; + X509CertImpl xcert = rec.getCertificate(); + + if (xcert != null) + if (!(rec.getStatus().equals(ICertRecord.STATUS_REVOKED))) { + count++; + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("serialNumber", + xcert.getSerialNumber().toString(16)); + rarg.addStringValue("serialNumberDecimal", + xcert.getSerialNumber().toString()); + rarg.addStringValue("subject", + xcert.getSubjectDN().toString()); + rarg.addLongValue("validNotBefore", + xcert.getNotBefore().getTime() / 1000); + rarg.addLongValue("validNotAfter", + xcert.getNotAfter().getTime() / 1000); + argSet.addRepeatRecord(rarg); + } + } + + header.addIntegerValue("verifiedRecordCount", count); + + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, "Error " + e); + throw e; + } + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java b/base/common/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java new file mode 100644 index 000000000..478df161d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java @@ -0,0 +1,624 @@ +// --- 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.cert; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPSearchResults; +import netscape.ldap.LDAPv2; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthMgrPlugin; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Allow agent to turn on/off authentication managers + * + * @version $Revision$, $Date$ + */ +public class RemoteAuthConfig extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -5803015919915253940L; + private final static String INFO = "RemoteAuthConfig"; + private final static String TPL_FILE = "remoteAuthConfig.template"; + private final static String ENABLE_REMOTE_CONFIG = "enableRemoteConfiguration"; + private final static String REMOTELY_SET_INSTANCES = "remotelySetInstances"; + private final static String MEMBER_OF = "memberOf"; + private final static String UNIQUE_MEMBER = "uniqueMember"; + + private String mFormPath = null; + private IAuthSubsystem mAuthSubsystem = null; + private IConfigStore mAuthConfig = null; + private IConfigStore mFileConfig = null; + private Vector<String> mRemotelySetInstances = new Vector<String>(); + private boolean mEnableRemoteConfiguration = false; + + /** + * Constructs RemoteAuthConfig servlet. + */ + public RemoteAuthConfig() { + super(); + } + + /** + * Initializes the servlet. + * + * Presence of "auths.enableRemoteConfiguration=true" in CMS.cfg + * enables remote configuration for authentication plugins. + * List of remotely set instances can be found in CMS.cfg + * at "auths.remotelySetInstances=<name1>,<name2>,...,<nameN>" + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mFileConfig = CMS.getConfigStore(); + mAuthConfig = mFileConfig.getSubStore("auths"); + try { + mEnableRemoteConfiguration = mAuthConfig.getBoolean(ENABLE_REMOTE_CONFIG, false); + } catch (EBaseException eb) { + // Thanks to design of getBoolean we have to catch but we will never get anything. + } + + String remoteList = null; + + try { + remoteList = mAuthConfig.getString(REMOTELY_SET_INSTANCES, null); + } catch (EBaseException eb) { + // Thanks to design of getString we have to catch but we will never get anything. + } + if (remoteList != null) { + StringTokenizer s = new StringTokenizer(remoteList, ","); + + while (s.hasMoreTokens()) { + String token = s.nextToken(); + + if (token != null && token.trim().length() > 0) { + mRemotelySetInstances.add(token.trim()); + } + } + } + + mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Serves HTTPS request. The format of this request is as follows: + * https://host:ee-port/remoteAuthConfig? + * op="add"|"delete"& + * instance=<instanceName>& + * of=<authPluginName>& + * host=<hostName>& + * port=<portNumber>& + * password=<password>& + * [adminDN=<adminDN>]& + * [uid=<uid>]& + * [baseDN=<baseDN>] + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + authenticate(cmsReq); + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + String host = req.getParameter("host"); + String port = req.getParameter("port"); + + String adminDN = req.getParameter("adminDN"); + String uid = req.getParameter("uid"); + String baseDN = req.getParameter("baseDN"); + String password = req.getParameter("password"); + + String replyTo = req.getParameter("replyTo"); + + if (replyTo != null && replyTo.length() > 0) { + ctx.addStringValue("replyTo", replyTo); + } + + if (mEnableRemoteConfiguration) { + String errMsg = null; + + if (adminDN != null && adminDN.length() > 0) { + errMsg = authenticateRemoteAdmin(host, port, adminDN, password); + } else { + errMsg = authenticateRemoteAdmin(host, port, uid, baseDN, password); + } + if (errMsg == null || errMsg.length() == 0) { + if (mAuthSubsystem != null && mAuthConfig != null) { + String op = req.getParameter("op"); + + if (op == null || op.length() == 0) { + header.addStringValue("error", "Undefined operation"); + } else { + header.addStringValue("op", op); + + if (op.equals("delete")) { + String plugin = req.getParameter("of"); + + if (isPluginListed(plugin)) { + String instance = req.getParameter("instance"); + + if (isInstanceListed(instance)) { + errMsg = deleteInstance(instance); + if (errMsg != null && errMsg.length() > 0) { + header.addStringValue("error", errMsg); + } else { + header.addStringValue("plugin", plugin); + header.addStringValue("instance", instance); + } + } else { + header.addStringValue("error", "Unknown instance " + + instance + "."); + } + } else { + header.addStringValue("error", "Unknown plugin name: " + plugin); + } + } else if (op.equals("add")) { + String plugin = req.getParameter("of"); + + if (isPluginListed(plugin)) { + String instance = req.getParameter("instance"); + + if (instance == null || instance.length() == 0) { + instance = makeInstanceName(); + } + if (isInstanceListed(instance)) { + header.addStringValue("error", "Instance name " + + instance + " is already in use."); + } else { + errMsg = addInstance(instance, plugin, + host, port, baseDN, + req.getParameter("dnPattern")); + if (errMsg != null && errMsg.length() > 0) { + header.addStringValue("error", errMsg); + } else { + header.addStringValue("plugin", plugin); + header.addStringValue("instance", instance); + } + } + } else { + header.addStringValue("error", "Unknown plugin name: " + plugin); + } + } else { + header.addStringValue("error", "Unsupported operation: " + op); + } + } + } else { + header.addStringValue("error", "Invalid configuration data."); + } + } else { + header.addStringValue("error", errMsg); + } + } else { + header.addStringValue("error", "Remote configuration is disabled."); + } + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + private String authenticateRemoteAdmin(String host, String port, + String adminDN, String password) { + if (host == null || host.length() == 0) { + return "Missing host name."; + } + if (port == null || port.length() == 0 || port.trim().length() == 0) { + return "Missing port number."; + } + if (adminDN == null || adminDN.length() == 0) { + return "Missing admin DN."; + } + if (password == null || password.length() == 0) { + return "Missing password."; + } + int p = 0; + + try { + p = Integer.parseInt(port.trim()); + } catch (NumberFormatException e) { + return "Invalid port number: " + port + " (" + e.toString() + ")"; + } + + boolean connected = false; + LDAPConnection c = new LDAPConnection(); + + try { + c.connect(host, p); + connected = true; + try { + c.authenticate(adminDN, password); + LDAPEntry entry = c.read(adminDN); + LDAPAttribute attr = entry.getAttribute(MEMBER_OF); + + if (attr != null) { + @SuppressWarnings("unchecked") + Enumeration<String> eVals = attr.getStringValues(); + + while (eVals.hasMoreElements()) { + String nextValue = eVals.nextElement(); + + if (nextValue.indexOf("Administrator") > -1) { + LDAPEntry groupEntry = c.read(nextValue); + + if (groupEntry != null) { + LDAPAttribute gAttr = groupEntry.getAttribute(UNIQUE_MEMBER); + + if (gAttr != null) { + @SuppressWarnings("unchecked") + Enumeration<String> eValues = gAttr.getStringValues(); + + while (eValues.hasMoreElements()) { + String value = eValues.nextElement(); + + if (value.equals(entry.getDN())) { + c.disconnect(); + return null; + } + } + } + } + break; + } + } + } else { + c.disconnect(); + return null; + } + + } catch (LDAPException e) { + + /* + switch (e.getLDAPResultCode()) { + case LDAPException.NO_SUCH_OBJECT: + case LDAPException.INVALID_CREDENTIALS: + case LDAPException.INSUFFICIENT_ACCESS_RIGHTS: + case LDAPException.LDAP_PARTIAL_RESULTS: + default: + } + */ + c.disconnect(); + return "LDAP error: " + e.toString(); + } + + if (connected) { + c.disconnect(); + } + } catch (LDAPException e) { + return "LDAP error: " + e.toString(); + } + + return "Access unauthorized"; + } + + private String authenticateRemoteAdmin(String host, String port, + String uid, String baseDN, + String password) { + if (host == null || host.length() == 0) { + return "Missing host name."; + } + if (port == null || port.length() == 0 || port.trim().length() == 0) { + return "Missing port number."; + } + if (uid == null || uid.length() == 0) { + return "Missing UID."; + } + if (uid.indexOf('*') > -1) { + return "Invalid UID: " + uid; + } + if (password == null || password.length() == 0) { + return "Missing password."; + } + int p = 0; + + try { + p = Integer.parseInt(port.trim()); + } catch (NumberFormatException e) { + return "Invalid port number: " + port + " (" + e.toString() + ")"; + } + if (baseDN == null || baseDN.length() == 0) { + return "Missing base DN."; + } + + boolean connected = false; + LDAPConnection c = new LDAPConnection(); + + try { + c.connect(host, p); + connected = true; + boolean memberOf = false; + LDAPSearchResults results = c.search(baseDN, LDAPv2.SCOPE_SUB, + "(uid=" + uid + ")", + null, false); + + while (results.hasMoreElements()) { + LDAPEntry entry = null; + + try { + entry = results.next(); + c.authenticate(entry.getDN(), password); + LDAPAttribute attr = entry.getAttribute(MEMBER_OF); + + if (attr != null) { + memberOf = true; + @SuppressWarnings("unchecked") + Enumeration<String> eVals = attr.getStringValues(); + + while (eVals.hasMoreElements()) { + String nextValue = eVals.nextElement(); + + if (nextValue.indexOf("Administrator") > -1) { + LDAPEntry groupEntry = c.read(nextValue); + + if (groupEntry != null) { + LDAPAttribute gAttr = groupEntry.getAttribute(UNIQUE_MEMBER); + + if (gAttr != null) { + @SuppressWarnings("unchecked") + Enumeration<String> eValues = gAttr.getStringValues(); + + while (eValues.hasMoreElements()) { + String value = eValues.nextElement(); + + if (value.equals(entry.getDN())) { + c.disconnect(); + return null; + } + } + } + } + break; + } + } + } + } catch (LDAPException e) { + switch (e.getLDAPResultCode()) { + case LDAPException.NO_SUCH_OBJECT: + continue; + + case LDAPException.INVALID_CREDENTIALS: + break; + + case LDAPException.INSUFFICIENT_ACCESS_RIGHTS: + break; + + case LDAPException.LDAP_PARTIAL_RESULTS: + break; + + default: + continue; + } + } + } + if (connected) { + c.disconnect(); + } + + if (!memberOf) { + return null; + } + } catch (LDAPException e) { + return "LDAP error: " + e.toString(); + } + + return "Access unauthorized"; + } + + private String addInstance(String instance, String plugin, + String host, String port, + String baseDN, String dnPattern) { + if (host == null || host.length() == 0) { + return "Missing host name."; + } + if (port == null || port.length() == 0) { + return "Missing port number."; + } + + IConfigStore c0 = mAuthConfig.getSubStore("instance"); + IConfigStore c1 = c0.makeSubStore(instance); + + c1.putString("dnpattern", dnPattern); + c1.putString("ldapByteAttributes", ""); + c1.putString("ldapStringAttributes", ""); + c1.putString("pluginName", plugin); + if (baseDN != null && baseDN.length() > 0) + c1.putString("ldap.basedn", baseDN); + c1.putString("ldap.minConns", ""); + c1.putString("ldap.maxConns", ""); + c1.putString("ldap.ldapconn.host", host); + c1.putString("ldap.ldapconn.port", port); + c1.putString("ldap.ldapconn.secureConn", "false"); + c1.putString("ldap.ldapconn.version", "3"); + + mRemotelySetInstances.add(instance); + + IAuthManager authMgrInst = mAuthSubsystem.getAuthManagerPlugin(plugin); + + if (authMgrInst != null) { + try { + authMgrInst.init(instance, plugin, c1); + } catch (EBaseException e) { + c0.removeSubStore(instance); + mRemotelySetInstances.remove(instance); + return e.toString(); + } + mAuthSubsystem.add(instance, authMgrInst); + } + + StringBuffer list = new StringBuffer(); + + for (int i = 0; i < mRemotelySetInstances.size(); i++) { + if (i > 0) + list.append(","); + list.append(mRemotelySetInstances.elementAt(i)); + } + + mAuthConfig.putString(REMOTELY_SET_INSTANCES, list.toString()); + + try { + mFileConfig.commit(false); + } catch (EBaseException e) { + c0.removeSubStore(instance); + mRemotelySetInstances.remove(instance); + return e.toString(); + } + + return null; + } + + private String deleteInstance(String instance) { + IConfigStore c = mAuthConfig.getSubStore("instance"); + + c.removeSubStore(instance); + + if (mRemotelySetInstances.remove(instance)) { + StringBuffer list = new StringBuffer(); + + for (int i = 0; i < mRemotelySetInstances.size(); i++) { + if (i > 0) + list.append(","); + list.append(mRemotelySetInstances.elementAt(i)); + } + + mAuthConfig.putString(REMOTELY_SET_INSTANCES, list.toString()); + } + + try { + mFileConfig.commit(false); + } catch (EBaseException e) { + return e.toString(); + } + mAuthSubsystem.delete(instance); + + return null; + } + + private boolean isPluginListed(String pluginName) { + boolean isListed = false; + + if (pluginName != null && pluginName.length() > 0) { + Enumeration<AuthMgrPlugin> e = mAuthSubsystem.getAuthManagerPlugins(); + + while (e.hasMoreElements()) { + AuthMgrPlugin plugin = e.nextElement(); + + if (pluginName.equals(plugin.getId())) { + isListed = true; + break; + } + } + } + + return isListed; + } + + private boolean isInstanceListed(String instanceName) { + boolean isListed = false; + + if (instanceName != null && instanceName.length() > 0) { + Enumeration<IAuthManager> e = mAuthSubsystem.getAuthManagers(); + + while (e.hasMoreElements()) { + IAuthManager authManager = e.nextElement(); + + if (instanceName.equals(authManager.getName())) { + isListed = true; + break; + } + } + } + + return isListed; + } + + private String makeInstanceName() { + Calendar now = Calendar.getInstance(); + int y = now.get(Calendar.YEAR); + String name = "R" + y; + + if (now.get(Calendar.MONTH) < 10) + name += "0"; + name += now.get(Calendar.MONTH); + if (now.get(Calendar.DAY_OF_MONTH) < 10) + name += "0"; + name += now.get(Calendar.DAY_OF_MONTH); + if (now.get(Calendar.HOUR_OF_DAY) < 10) + name += "0"; + name += now.get(Calendar.HOUR_OF_DAY); + if (now.get(Calendar.MINUTE) < 10) + name += "0"; + name += now.get(Calendar.MINUTE); + if (now.get(Calendar.SECOND) < 10) + name += "0"; + name += now.get(Calendar.SECOND); + return name; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/RenewalServlet.java b/base/common/src/com/netscape/cms/servlet/cert/RenewalServlet.java new file mode 100644 index 000000000..223121577 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/RenewalServlet.java @@ -0,0 +1,523 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Calendar; +import java.util.Date; +import java.util.Enumeration; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; + +import netscape.security.extensions.CertInfo; +import netscape.security.x509.CertificateSerialNumber; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +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.base.IArgBlock; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; + +/** + * Certificate Renewal + * + * @version $Revision$, $Date$ + */ +public class RenewalServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -3094124661102395244L; + + // renewal templates. + public static final String RENEWAL_SUCCESS_TEMPLATE = "RenewalSuccess.template"; + + // http params + public static final String CERT_TYPE = "certType"; + public static final String SERIAL_NO = "serialNo"; + // XXX can't do pkcs10 cause it's got no serial no. + // (unless put serial no in pki attributes) + // public static final String PKCS10 = "pkcs10"; + public static final String IMPORT_CERT = "importCert"; + + private String mRenewalSuccessTemplate = RENEWAL_SUCCESS_TEMPLATE; + private ICMSTemplateFiller mRenewalSuccessFiller = new ImportCertsTemplateFiller(); + + public RenewalServlet() { + super(); + } + + /** + * initialize the servlet. This servlet makes use of the + * template file "RenewalSuccess.template" to render the + * response + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success template. has same info as enrollment. + mTemplates.remove(CMSRequest.SUCCESS); + try { + mRenewalSuccessTemplate = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE); + if (mRenewalSuccessTemplate == null) + mRenewalSuccessTemplate = RENEWAL_SUCCESS_TEMPLATE; + String fillername = + sc.getInitParameter(PROP_SUCCESS_TEMPLATE_FILLER); + + if (fillername != null) { + ICMSTemplateFiller filler = newFillerObject(fillername); + + if (filler != null) + mRenewalSuccessFiller = filler; + } + } catch (Exception e) { + // this should never happen. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IMP_INIT_SERV_ERR", e.toString(), + mId)); + } + + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + long startTime = CMS.getCurrentDate().getTime(); + IArgBlock httpParams = cmsReq.getHttpParams(); + HttpServletRequest httpReq = cmsReq.getHttpReq(); + + // renewal requires either: + // - coming from ee: + // - old cert from ssl client auth + // - old certs from auth manager + // - coming from agent or trusted RA: + // - serial no of cert to be renewed. + + BigInteger old_serial_no = null; + X509CertImpl old_cert = null; + X509CertImpl renewed_cert = null; + Date notBefore = null; + Date notAfter = null; + boolean doSaveAuthToken = false; + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "renew"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String authMgr = AuditFormat.NOAUTH; + + if (authToken != null && !mAuthMgr.equals("sslClientCertAuthMgr")) { + authMgr = + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } + + // coming from agent + if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + X509Certificate[] cert = new X509Certificate[1]; + + old_serial_no = getCertFromAgent(httpParams, cert); + old_cert = (X509CertImpl) cert[0]; + + // optional validity params from input. + int beginYear = httpParams.getValueAsInt("beginYear", -1); + int beginMonth = httpParams.getValueAsInt("beginMonth", -1); + int beginDate = httpParams.getValueAsInt("beginDate", -1); + int endYear = httpParams.getValueAsInt("endYear", -1); + int endMonth = httpParams.getValueAsInt("endMonth", -1); + int endDate = httpParams.getValueAsInt("endDate", -1); + + if (beginYear != -1 && beginMonth != -1 && beginDate != -1 && + endYear != -1 && endMonth != -1 && endDate != -1) { + Calendar calendar = Calendar.getInstance(); + calendar.set(beginYear, beginMonth, beginDate); + notBefore = calendar.getTime(); + calendar.set(endYear, endMonth, endDate); + notAfter = calendar.getTime(); + } + } // coming from client + else { + // from auth manager + X509CertImpl[] cert = new X509CertImpl[1]; + + old_serial_no = getCertFromAuthMgr(authToken, cert); + old_cert = cert[0]; + } + + IRequest req = null; + + try { + // get ready to send request to request queue. + X509CertInfo new_certInfo = null; + + req = mRequestQueue.newRequest(IRequest.RENEWAL_REQUEST); + req.setExtData(IRequest.OLD_SERIALS, new BigInteger[] { old_serial_no }); + if (old_cert != null) { + req.setExtData(IRequest.OLD_CERTS, + new X509CertImpl[] { old_cert } + ); + // create new certinfo from old_cert contents. + X509CertInfo old_certInfo = (X509CertInfo) + ((X509CertImpl) old_cert).get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + + new_certInfo = new X509CertInfo(old_certInfo.getEncodedInfo()); + } else { + // if no old cert (came from RA agent) create new cert info + // (serializable) to pass through policies. And set the old + // serial number to pick up. + new_certInfo = new CertInfo(); + new_certInfo.set(X509CertInfo.SERIAL_NUMBER, + new CertificateSerialNumber(old_serial_no)); + } + + if (notBefore == null || notAfter == null) { + notBefore = new Date(0); + notAfter = new Date(0); + } + new_certInfo.set(X509CertInfo.VALIDITY, + new CertificateValidity(notBefore, notAfter)); + req.setExtData(IRequest.CERT_INFO, new X509CertInfo[] { new_certInfo } + ); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SETTING_RENEWAL_VALIDITY_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SETTING_RENEWAL_VALIDITY_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SETTING_RENEWAL_VALIDITY_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SETTING_RENEWAL_VALIDITY_ERROR")); + } + + saveHttpHeaders(httpReq, req); + saveHttpParams(httpParams, req); + if (doSaveAuthToken) + saveAuthToken(authToken, req); + cmsReq.setIRequest(req); + + // send request to request queue. + mRequestQueue.processRequest(req); + + // for audit log + String initiative = null; + String agentID = null; + + if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + agentID = authToken.getInString("userid"); + initiative = AuditFormat.FROMAGENT + " agentID: " + agentID; + } else { + // request is from eegateway, so fromUser. + initiative = AuditFormat.FROMUSER; + } + + // check resulting status + RequestStatus status = req.getRequestStatus(); + + if (status != RequestStatus.COMPLETE) { + cmsReq.setIRequestStatus(); + // audit log the status + if (status == RequestStatus.REJECTED) { + Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration<String> msgs = messages.elements(); + StringBuffer wholeMsg = new StringBuffer(); + + while (msgs.hasMoreElements()) { + wholeMsg.append("\n"); + wholeMsg.append(msgs.nextElement()); + } + + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + old_cert.getSubjectDN(), + old_cert.getSerialNumber().toString(16), + "violation: " + + wholeMsg.toString() } + // wholeMsg}, + // ILogger.L_MULTILINE + ); + } else { // no policy violation, from agent + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + old_cert.getSubjectDN(), + old_cert.getSerialNumber().toString(16), + "" } + ); + } + } else { // other imcomplete status + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + status.toString(), + old_cert.getSubjectDN(), + old_cert.getSerialNumber().toString(16), + "" } + ); + } + return; + } + + // service error + Integer result = req.getExtDataInInteger(IRequest.RESULT); + + CMS.debug( + "RenewalServlet: Result for request " + req.getRequestId() + " is " + result); + if (result.equals(IRequest.RES_ERROR)) { + CMS.debug( + "RenewalServlet: Result for request " + req.getRequestId() + " is error."); + + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(req.getExtDataInString(IRequest.ERROR)); + String[] svcErrors = + req.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + //System.out.println( + //"revocation servlet: setting error description "+ + //err.toString()); + cmsReq.setErrorDescription(err); + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + "completed with error: " + + err, + old_cert.getSubjectDN(), + old_cert.getSerialNumber().toString(16), + "" } + ); + + } + } + } + return; + } + + // success. + X509CertImpl[] certs = req.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + renewed_cert = certs[0]; + respondSuccess(cmsReq, renewed_cert); + long endTime = CMS.getCurrentDate().getTime(); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + req.getRequestId(), + initiative, + authMgr, + "completed", + old_cert.getSubjectDN(), + old_cert.getSerialNumber().toString(16), + "new serial number: 0x" + + renewed_cert.getSerialNumber().toString(16) + " time: " + (endTime - startTime) } + ); + + return; + } + + private void respondSuccess( + CMSRequest cmsReq, X509CertImpl renewed_cert) + throws EBaseException { + cmsReq.setResult(new X509CertImpl[] { renewed_cert } + ); + cmsReq.setStatus(CMSRequest.SUCCESS); + + // check if cert should be imported. + // browser must have input type set to nav or cartman since + // there's no other way to tell + + IArgBlock httpParams = cmsReq.getHttpParams(); + + if (checkImportCertToNav(cmsReq.getHttpResp(), + httpParams, renewed_cert)) { + return; + } else { + try { + renderTemplate(cmsReq, + mRenewalSuccessTemplate, mRenewalSuccessFiller); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGE_ERROR_DISPLAY_TEMPLATE_1", + mRenewalSuccessTemplate, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + return; + } + + protected BigInteger getRenewedCert(ICertRecord certRec) + throws EBaseException { + BigInteger renewedCert = null; + String serial = null; + MetaInfo meta = certRec.getMetaInfo(); + + if (meta == null) { + log(ILogger.LL_INFO, + "no meta info in cert serial 0x" + certRec.getSerialNumber().toString(16)); + return null; + } + serial = (String) meta.get(ICertRecord.META_RENEWED_CERT); + if (serial == null) { + log(ILogger.LL_INFO, + "no renewed cert in cert 0x" + certRec.getSerialNumber().toString(16)); + return null; + } + renewedCert = new BigInteger(serial); + log(ILogger.LL_INFO, + "renewed cert serial 0x" + renewedCert.toString(16) + "found for 0x" + + certRec.getSerialNumber().toString(16)); + return renewedCert; + } + + /** + * get certs to renew from agent. + */ + private BigInteger getCertFromAgent( + IArgBlock httpParams, X509Certificate[] certContainer) + throws EBaseException { + BigInteger serialno = null; + X509Certificate cert = null; + + // get serial no + serialno = httpParams.getValueAsBigInteger(SERIAL_NO, null); + if (serialno == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SERIALNO_FOR_RENEW")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SERIALNO_FOR_RENEW")); + } + // get cert from db if we're cert authority. + if (mAuthority instanceof ICertificateAuthority) { + cert = getX509Certificate(serialno); + if (cert == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SERIALNO_FOR_RENEW_1", serialno.toString(16))); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_RENEWAL")); + } + } + certContainer[0] = cert; + return serialno; + } + + /** + * get cert to renew from auth manager + */ + private BigInteger getCertFromAuthMgr( + IAuthToken authToken, X509Certificate[] certContainer) + throws EBaseException { + X509CertImpl cert = + authToken.getInCert(AuthToken.TOKEN_CERT); + + if (cert == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTS_RENEW_FROM_AUTHMGR")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CERTS_RENEW_FROM_AUTHMGR")); + } + if (mAuthority instanceof ICertificateAuthority && + !isCertFromCA(cert)) { + log(ILogger.LL_FAILURE, "certficate from auth manager for " + + " renewal is not from this ca."); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_RENEWAL")); + } + certContainer[0] = cert; + BigInteger serialno = ((X509Certificate) cert).getSerialNumber(); + + return serialno; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java b/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java new file mode 100644 index 000000000..22aa29eda --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java @@ -0,0 +1,392 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Random; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +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.base.IArgBlock; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Utils; + +/** + * Perform the first step in revoking a certificate + * + * @version $Revision$, $Date$ + */ +public class RevocationServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -9086730404084717413L; + private final static String PROP_REVOKEBYDN = "revokeByDN"; + // revocation templates. + private final static String TPL_FILE = "reasonToRevoke.template"; + + // http params + public static final String SERIAL_NO = "serialNo"; + // XXX can't do pkcs10 cause it's got no serial no. + // (unless put serial no in pki attributes) + // public static final String PKCS10 = "pkcs10"; + public static final String REASON_CODE = "reasonCode"; + + private String mFormPath = null; + private boolean mRevokeByDN = true; + + private Random mRandom = null; + private Nonces mNonces = null; + + public RevocationServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses + * the template file "reasonToRevoke.template" to render the + * result. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success template. has same info as enrollment. + mTemplates.remove(CMSRequest.SUCCESS); + + mFormPath = "/" + TPL_FILE; + try { + mFormPath = sc.getInitParameter( + PROP_SUCCESS_TEMPLATE); + if (mFormPath == null) + mFormPath = "/" + TPL_FILE; + + if (mAuthority instanceof ICertificateAuthority) { + if (((ICertificateAuthority) mAuthority).noncesEnabled()) { + mNonces = ((ICertificateAuthority) mAuthority).getNonces(); + mRandom = new Random(); + } + } + + // set to false by revokeByDN=false in web.xml + mRevokeByDN = false; + String tmp = sc.getInitParameter(PROP_REVOKEBYDN); + + if (tmp == null || tmp.trim().equalsIgnoreCase("false")) + mRevokeByDN = false; + else if (tmp.trim().equalsIgnoreCase("true")) + mRevokeByDN = true; + } catch (Exception e) { + } + } + + /** + * Process the HTTP request. Note that this servlet does not + * actually perform the certificate revocation. This is the first + * step in the multi-step revocation process. (the next step is + * in the ReasonToRevoke servlet. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + IArgBlock httpParams = cmsReq.getHttpParams(); + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + // revocation requires either: + // - coming from ee: + // - old cert from ssl client auth + // - old certs from auth manager + // - coming from agent or trusted RA: + // - serial no of cert to be revoked. + + BigInteger old_serial_no = null; + X509CertImpl old_cert = null; + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "submit"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + // coming from agent + if (mAuthMgr != null && mAuthMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID)) { + X509Certificate[] cert = new X509Certificate[1]; + + old_serial_no = getCertFromAgent(httpParams, cert); + old_cert = (X509CertImpl) cert[0]; + } // coming from client + else { + // from auth manager + X509CertImpl[] cert = new X509CertImpl[1]; + + old_serial_no = getCertFromAuthMgr(authToken, cert); + old_cert = cert[0]; + } + + header.addStringValue("serialNumber", old_cert.getSerialNumber().toString(16)); + header.addStringValue("serialNumberDecimal", old_cert.getSerialNumber().toString()); + // header.addStringValue("subject", old_cert.getSubjectDN().toString()); + // header.addLongValue("validNotBefore", old_cert.getNotBefore().getTime()/1000); + // header.addLongValue("validNotAfter", old_cert.getNotAfter().getTime()/1000); + + if (mNonces != null) { + long n = mRandom.nextLong(); + long m = mNonces.addNonce(n, (X509Certificate) old_cert); + if ((n + m) != 0) { + header.addStringValue("nonce", Long.toString(m)); + } + } + + boolean noInfo = false; + X509CertImpl[] certsToRevoke = null; + + if (mAuthority instanceof ICertificateAuthority) { + certsToRevoke = ((ICertificateAuthority) mAuthority).getCertificateRepository().getX509Certificates( + old_cert.getSubjectDN().toString(), + ICertificateRepository.ALL_UNREVOKED_CERTS); + + } else if (mAuthority instanceof IRegistrationAuthority) { + IRequest req = mRequestQueue.newRequest(IRequest.GETCERTS_REQUEST); + String filter = "(&(" + ICertRecord.ATTR_X509CERT + "." + + X509CertInfo.SUBJECT + "=" + + old_cert.getSubjectDN().toString() + ")(|(" + + ICertRecord.ATTR_CERT_STATUS + "=" + + ICertRecord.STATUS_VALID + ")(" + + ICertRecord.ATTR_CERT_STATUS + "=" + + ICertRecord.STATUS_EXPIRED + ")))"; + + req.setExtData(IRequest.CERT_FILTER, filter); + mRequestQueue.processRequest(req); + RequestStatus status = req.getRequestStatus(); + + if (status == RequestStatus.COMPLETE) { + header.addStringValue("request", req.getRequestId().toString()); + Enumeration<String> enum1 = req.getExtDataKeys(); + + while (enum1.hasMoreElements()) { + String name = enum1.nextElement(); + + if (name.equals(IRequest.OLD_CERTS)) { + X509CertImpl[] certs = req.getExtDataInCertArray(IRequest.OLD_CERTS); + + certsToRevoke = certs; + } + } + } else { + noInfo = true; + } + } + + boolean authorized = false; + + if (certsToRevoke != null && certsToRevoke.length > 0) { + for (int i = 0; i < certsToRevoke.length; i++) { + if (old_cert.getSerialNumber().equals(certsToRevoke[i].getSerialNumber())) { + authorized = true; + break; + } + } + } + + if (!noInfo && (certsToRevoke == null || certsToRevoke.length == 0 || + (!authorized))) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CA_CERT_ALREADY_REVOKED_1", old_serial_no.toString(16))); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CERT_ALREADY_REVOKED")); + } + + if (!mRevokeByDN || noInfo) { + certsToRevoke = new X509CertImpl[1]; + certsToRevoke[0] = old_cert; + try { + byte[] ba = old_cert.getEncoded(); + // Do base 64 encoding + + header.addStringValue("b64eCertificate", Utils.base64encode(ba)); + } catch (CertificateEncodingException e) { + } + } + + if (certsToRevoke != null && certsToRevoke.length > 0) { + header.addIntegerValue("totalRecordCount", certsToRevoke.length); + header.addIntegerValue("verifiedRecordCount", certsToRevoke.length); + + for (int i = 0; i < certsToRevoke.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("serialNumber", + certsToRevoke[i].getSerialNumber().toString(16)); + rarg.addStringValue("serialNumberDecimal", + certsToRevoke[i].getSerialNumber().toString()); + rarg.addStringValue("subject", + certsToRevoke[i].getSubjectDN().toString()); + rarg.addLongValue("validNotBefore", + certsToRevoke[i].getNotBefore().getTime() / 1000); + rarg.addLongValue("validNotAfter", + certsToRevoke[i].getNotAfter().getTime() / 1000); + argSet.addRepeatRecord(rarg); + } + } else { + header.addIntegerValue("totalRecordCount", 0); + header.addIntegerValue("verifiedRecordCount", 0); + } + + // set revocation reason, default to unspecified if not set. + int reasonCode = httpParams.getValueAsInt(REASON_CODE, 0); + + header.addIntegerValue("reason", reasonCode); + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + return; + } + + /** + * get cert to revoke from agent. + */ + private BigInteger getCertFromAgent( + IArgBlock httpParams, X509Certificate[] certContainer) + throws EBaseException { + BigInteger serialno = null; + X509Certificate cert = null; + + // get serial no + serialno = httpParams.getValueAsBigInteger(SERIAL_NO, null); + if (serialno == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SERIALNO_FOR_REVOKE")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SERIALNO_FOR_REVOKE")); + } + + // get cert from db if we're cert authority. + if (mAuthority instanceof ICertificateAuthority) { + cert = getX509Certificate(serialno); + if (cert == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_INVALID_CERT_FOR_REVOCATION")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_REVOCATION")); + } + } + certContainer[0] = cert; + return serialno; + } + + /** + * get cert to revoke from auth manager + */ + private BigInteger getCertFromAuthMgr( + IAuthToken authToken, X509Certificate[] certContainer) + throws EBaseException { + X509CertImpl cert = + authToken.getInCert(AuthToken.TOKEN_CERT); + + if (cert == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTS_REVOKE_FROM_AUTHMGR")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CERTS_REVOKE_FROM_AUTHMGR")); + } + if (mAuthority instanceof ICertificateAuthority && + !isCertFromCA(cert)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_CERT_FOR_REVOCATION")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_CERT_FOR_REVOCATION")); + } + certContainer[0] = cert; + BigInteger serialno = ((X509Certificate) cert).getSerialNumber(); + + return serialno; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java new file mode 100644 index 000000000..cfc562d71 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java @@ -0,0 +1,97 @@ +// --- 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.cert; + +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.x509.RevokedCertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; + +/** + * Certificates Template filler. + * must have list of certificates in result. + * looks at inputs: certtype. + * outputs: + * - cert type from http input (if any) + * - CA chain + * - authority name (RM, CM, DRM) + * - scheme:host:port of server. + * array of one or more + * - cert serial number + * - cert pretty print + * - cert in base 64 encoding. + * - cmmf blob to import + * + * @version $Revision$, $Date$ + */ +class RevocationSuccessTemplateFiller implements ICMSTemplateFiller { + public final static String SERIAL_NO = "serialNo"; + + public RevocationSuccessTemplateFiller() { + } + + /** + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) + throws Exception { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + // set host name and port. + HttpServletRequest httpReq = cmsReq.getHttpReq(); + String host = httpReq.getServerName(); + int port = httpReq.getServerPort(); + String scheme = httpReq.getScheme(); + + fixed.set(ICMSTemplateFiller.HOST, host); + fixed.set(ICMSTemplateFiller.PORT, Integer.valueOf(port)); + fixed.set(ICMSTemplateFiller.SCHEME, scheme); + + // this authority + fixed.set(ICMSTemplateFiller.AUTHORITY, + (String) authority.getOfficialName()); + + // XXX CA chain. + + RevokedCertImpl[] revoked = + (RevokedCertImpl[]) cmsReq.getResult(); + + // revoked certs. + for (int i = 0; i < revoked.length; i++) { + IArgBlock repeat = CMS.createArgBlock(); + + repeat.set(SERIAL_NO, revoked[i].getSerialNumber()); + params.addRepeatRecord(repeat); + } + + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/SrchCerts.java b/base/common/src/com/netscape/cms/servlet/cert/SrchCerts.java new file mode 100644 index 000000000..3602515c9 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/SrchCerts.java @@ -0,0 +1,762 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.PublicKey; +import java.util.Calendar; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.provider.RSAPublicKey; +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; + +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.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.dbs.certdb.IRevocationInfo; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Search for certificates matching complex query filter + * + * @version $Revision$, $Date$ + */ +public class SrchCerts extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -5876805830088921643L; + private final static String TPL_FILE = "srchCert.template"; + private final static String INFO = "SrchCerts"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReturns"; + + private final static String CURRENT_TIME = "currentTime"; + private final static int MAX_RESULTS = 1000; + + private ICertificateRepository mCertDB = null; + private X500Name mAuthName = null; + private String mFormPath = null; + private int mMaxReturns = MAX_RESULTS; + private int mTimeLimits = 30; /* in seconds */ + private boolean mUseClientFilter = false; + + /** + * Constructs query key servlet. + */ + public SrchCerts() { + super(); + } + + /** + * initialize the servlet. This servlet uses srchCert.template + * to render the response + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to render own template. + mTemplates.remove(CMSRequest.SUCCESS); + + if (mAuthority instanceof ISubsystem) { + ISubsystem sub = (ISubsystem) mAuthority; + IConfigStore authConfig = sub.getConfigStore(); + + if (authConfig != null) { + try { + mMaxReturns = authConfig.getInteger(PROP_MAX_SEARCH_RETURNS, MAX_RESULTS); + } catch (EBaseException e) { + // do nothing + } + } + } + if (mAuthority instanceof ICertificateAuthority) { + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + + mCertDB = ca.getCertificateRepository(); + mAuthName = ca.getX500Name(); + } + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + /* Server-Side time limit */ + try { + int maxResults = Integer.parseInt(sc.getInitParameter("maxResults")); + if (maxResults < mMaxReturns) + mMaxReturns = maxResults; + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + + /* useClientFilter should be off by default. We keep + this parameter around so that we do not break + the client applications that submits raw LDAP + filter into this servlet. */ + if (sc.getInitParameter("useClientFilter") != null && + sc.getInitParameter("useClientFilter").equalsIgnoreCase("true")) { + mUseClientFilter = true; + } + } + + private boolean isOn(HttpServletRequest req, String name) { + String inUse = req.getParameter(name); + if (inUse == null) { + return false; + } + if (inUse.equals("on")) { + return true; + } + return false; + } + + private boolean isOff(HttpServletRequest req, String name) { + String inUse = req.getParameter(name); + if (inUse == null) { + return false; + } + if (inUse.equals("off")) { + return true; + } + return false; + } + + private void buildCertStatusFilter(HttpServletRequest req, StringBuffer filter) { + if (!isOn(req, "statusInUse")) { + return; + } + String status = req.getParameter("status"); + filter.append("(certStatus="); + filter.append(status); + filter.append(")"); + } + + private void buildProfileFilter(HttpServletRequest req, StringBuffer filter) { + if (!isOn(req, "profileInUse")) { + return; + } + String profile = req.getParameter("profile"); + filter.append("(certMetaInfo=profileId:"); + filter.append(profile); + filter.append(")"); + } + + private void buildBasicConstraintsFilter(HttpServletRequest req, StringBuffer filter) { + if (!isOn(req, "basicConstraintsInUse")) { + return; + } + filter.append("(x509cert.BasicConstraints.isCA=on)"); + } + + private void buildSerialNumberRangeFilter(HttpServletRequest req, StringBuffer filter) { + if (!isOn(req, "serialNumberRangeInUse")) { + return; + } + boolean changed = false; + String serialFrom = req.getParameter("serialFrom"); + if (serialFrom != null && !serialFrom.equals("")) { + filter.append("(certRecordId>=" + serialFrom + ")"); + changed = true; + } + String serialTo = req.getParameter("serialTo"); + if (serialTo != null && !serialTo.equals("")) { + filter.append("(certRecordId<=" + serialTo + ")"); + changed = true; + } + if (!changed) { + filter.append("(certRecordId=*)"); + } + } + + private void buildAVAFilter(HttpServletRequest req, String paramName, + String avaName, StringBuffer lf, String match) { + String val = req.getParameter(paramName); + if (val != null && !val.equals("")) { + if (match != null && match.equals("exact")) { + lf.append("(|"); + lf.append("(x509cert.subject=*"); + lf.append(avaName); + lf.append("="); + lf.append(escapeValueRfc1779(val, true)); + lf.append(",*)"); + lf.append("(x509cert.subject=*"); + lf.append(avaName); + lf.append("="); + lf.append(escapeValueRfc1779(val, true)); + lf.append(")"); + lf.append(")"); + } else { + lf.append("(x509cert.subject=*"); + lf.append(avaName); + lf.append("="); + lf.append("*"); + lf.append(escapeValueRfc1779(val, true)); + lf.append("*)"); + } + } + } + + private void buildSubjectFilter(HttpServletRequest req, StringBuffer filter) { + if (!isOn(req, "subjectInUse")) { + return; + } + StringBuffer lf = new StringBuffer(); + String match = req.getParameter("match"); + + buildAVAFilter(req, "eMail", "E", lf, match); + buildAVAFilter(req, "commonName", "CN", lf, match); + buildAVAFilter(req, "userID", "UID", lf, match); + buildAVAFilter(req, "orgUnit", "OU", lf, match); + buildAVAFilter(req, "org", "O", lf, match); + buildAVAFilter(req, "locality", "L", lf, match); + buildAVAFilter(req, "state", "ST", lf, match); + buildAVAFilter(req, "country", "C", lf, match); + + if (lf.length() == 0) { + filter.append("(x509cert.subject=*)"); + return; + } + if (match.equals("exact")) { + filter.append("(&"); + filter.append(lf); + filter.append(")"); + } else { + filter.append("(|"); + filter.append(lf); + filter.append(")"); + } + } + + private void buildRevokedByFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "revokedByInUse")) { + return; + } + String revokedBy = req.getParameter("revokedBy"); + if (revokedBy == null || revokedBy.equals("")) { + filter.append("(certRevokedBy=*)"); + } else { + filter.append("(certRevokedBy="); + filter.append(revokedBy); + filter.append(")"); + } + } + + private void buildDateFilter(HttpServletRequest req, String prefix, + String outStr, long adjustment, + StringBuffer filter) { + long epoch = 0; + try { + epoch = Long.parseLong(req.getParameter(prefix)); + } catch (NumberFormatException e) { + // exception safely ignored + } + Calendar from = Calendar.getInstance(); + from.setTimeInMillis(epoch); + CMS.debug("buildDateFilter epoch=" + req.getParameter(prefix)); + CMS.debug("buildDateFilter from=" + from); + filter.append("("); + filter.append(outStr); + filter.append(Long.toString(from.getTimeInMillis() + adjustment)); + filter.append(")"); + } + + private void buildRevokedOnFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "revokedOnInUse")) { + return; + } + buildDateFilter(req, "revokedOnFrom", "certRevokedOn>=", 0, filter); + buildDateFilter(req, "revokedOnTo", "certRevokedOn<=", 86399999, + filter); + } + + private void buildRevocationReasonFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "revocationReasonInUse")) { + return; + } + String reasons = req.getParameter("revocationReason"); + if (reasons == null) { + return; + } + String queryCertFilter = null; + StringTokenizer st = new StringTokenizer(reasons, ","); + if (st.hasMoreTokens()) { + filter.append("(|"); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (queryCertFilter == null) { + queryCertFilter = ""; + } + filter.append("(x509cert.certRevoInfo="); + filter.append(token); + filter.append(")"); + } + filter.append(")"); + } + } + + private void buildIssuedByFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "issuedByInUse")) { + return; + } + String issuedBy = req.getParameter("issuedBy"); + if (issuedBy == null || issuedBy.equals("")) { + filter.append("(certIssuedBy=*)"); + } else { + filter.append("(certIssuedBy="); + filter.append(issuedBy); + filter.append(")"); + } + } + + private void buildIssuedOnFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "issuedOnInUse")) { + return; + } + buildDateFilter(req, "issuedOnFrom", "certCreateTime>=", 0, filter); + buildDateFilter(req, "issuedOnTo", "certCreateTime<=", 86399999, + filter); + } + + private void buildValidNotBeforeFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "validNotBeforeInUse")) { + return; + } + buildDateFilter(req, "validNotBeforeFrom", "x509cert.notBefore>=", + 0, filter); + buildDateFilter(req, "validNotBeforeTo", "x509cert.notBefore<=", + 86399999, filter); + } + + private void buildValidNotAfterFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "validNotAfterInUse")) { + return; + } + buildDateFilter(req, "validNotAfterFrom", "x509cert.notAfter>=", + 0, filter); + buildDateFilter(req, "validNotAfterTo", "x509cert.notAfter<=", + 86399999, filter); + } + + private void buildValidityLengthFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "validityLengthInUse")) { + return; + } + String op = req.getParameter("validityOp"); + long count = 0; + try { + count = Long.parseLong(req.getParameter("count")); + } catch (NumberFormatException e) { + // safely ignore + } + long unit = 0; + try { + unit = Long.parseLong(req.getParameter("unit")); + } catch (NumberFormatException e) { + // safely ignore + } + filter.append("("); + filter.append("x509cert.duration"); + filter.append(op); + filter.append(count * unit); + filter.append(")"); + } + + private void buildCertTypeFilter(HttpServletRequest req, + StringBuffer filter) { + if (!isOn(req, "certTypeInUse")) { + return; + } + if (isOn(req, "SSLClient")) { + filter.append("(x509cert.nsExtension.SSLClient=on)"); + } else if (isOff(req, "SSLClient")) { + filter.append("(x509cert.nsExtension.SSLClient=off)"); + } + if (isOn(req, "SSLServer")) { + filter.append("(x509cert.nsExtension.SSLServer=on)"); + } else if (isOff(req, "SSLServer")) { + filter.append("(x509cert.nsExtension.SSLServer=off)"); + } + if (isOn(req, "SecureEmail")) { + filter.append("(x509cert.nsExtension.SecureEmail=on)"); + } else if (isOff(req, "SecureEmail")) { + filter.append("(x509cert.nsExtension.SecureEmail=off)"); + } + if (isOn(req, "SubordinateSSLCA")) { + filter.append("(x509cert.nsExtension.SubordinateSSLCA=on)"); + } else if (isOff(req, "SubordinateSSLCA")) { + filter.append("(x509cert.nsExtension.SubordinateSSLCA=off)"); + } + if (isOn(req, "SubordinateEmailCA")) { + filter.append("(x509cert.nsExtension.SubordinateEmailCA=on)"); + } else if (isOff(req, "SubordinateEmailCA")) { + filter.append("(x509cert.nsExtension.SubordinateEmailCA=off)"); + } + } + + public String buildFilter(HttpServletRequest req) { + String queryCertFilter = req.getParameter("queryCertFilter"); + + StringBuffer filter = new StringBuffer(); + buildSerialNumberRangeFilter(req, filter); + buildSubjectFilter(req, filter); + buildRevokedByFilter(req, filter); + buildRevokedOnFilter(req, filter); + buildRevocationReasonFilter(req, filter); + buildIssuedByFilter(req, filter); + buildIssuedOnFilter(req, filter); + buildValidNotBeforeFilter(req, filter); + buildValidNotAfterFilter(req, filter); + buildValidityLengthFilter(req, filter); + buildCertTypeFilter(req, filter); + buildCertStatusFilter(req, filter); + buildProfileFilter(req, filter); + buildBasicConstraintsFilter(req, filter); + + if (mUseClientFilter) { + CMS.debug("useClientFilter=true"); + } else { + CMS.debug("useClientFilter=false"); + CMS.debug("client queryCertFilter = " + queryCertFilter); + queryCertFilter = "(&" + filter.toString() + ")"; + } + CMS.debug("queryCertFilter = " + queryCertFilter); + return queryCertFilter; + } + + /** + * Serves HTTP request. This format of this request is as follows: + * queryCert? + * [maxCount=<number>] + * [queryFilter=<filter>] + * [revokeAll=<filter>] + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String revokeAll = null; + EBaseException error = null; + int maxResults = -1; + int timeLimit = -1; + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + revokeAll = req.getParameter("revokeAll"); + + String maxResultsStr = req.getParameter("maxResults"); + + if (maxResultsStr != null && maxResultsStr.length() > 0) + maxResults = Integer.parseInt(maxResultsStr); + String timeLimitStr = req.getParameter("timeLimit"); + + if (timeLimitStr != null && timeLimitStr.length() > 0) + timeLimit = Integer.parseInt(timeLimitStr); + + String queryCertFilter = buildFilter(req); + process(argSet, header, queryCertFilter, + revokeAll, maxResults, timeLimit, req, resp, locale[0]); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + cmsReq.setStatus(CMSRequest.SUCCESS); + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Process the key search. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + String filter, String revokeAll, + int maxResults, int timeLimit, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) + throws EBaseException { + try { + long startTime = CMS.getCurrentDate().getTime(); + + if (filter.indexOf(CURRENT_TIME, 0) > -1) { + filter = insertCurrentTime(filter); + } + + // xxx the filter includes serial number range??? + if (maxResults == -1 || maxResults > mMaxReturns) { + CMS.debug("Resetting maximum of returned results from " + maxResults + " to " + mMaxReturns); + maxResults = mMaxReturns; + } + if (timeLimit == -1 || timeLimit > mTimeLimits) { + CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits); + timeLimit = mTimeLimits; + } + CMS.debug("Start searching ... " + + "filter=" + filter + " maxreturns=" + maxResults + " timelimit=" + timeLimit); + Enumeration<ICertRecord> e = mCertDB.searchCertificates(filter, maxResults, timeLimit); + + int count = 0; + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = e.nextElement(); + + if (rec != null) { + count++; + IArgBlock rarg = CMS.createArgBlock(); + + fillRecordIntoArg(rec, rarg); + argSet.addRepeatRecord(rarg); + } + } + + long endTime = CMS.getCurrentDate().getTime(); + + header.addStringValue("op", req.getParameter("op")); + if (mAuthName != null) + header.addStringValue("issuerName", mAuthName.toString()); + header.addStringValue("time", Long.toString(endTime - startTime)); + header.addStringValue("serviceURL", req.getRequestURI()); + header.addStringValue("queryFilter", filter); + if (revokeAll != null) + header.addStringValue("revokeAll", revokeAll); + header.addIntegerValue("totalRecordCount", count); + header.addIntegerValue("maxSize", maxResults); + } catch (EBaseException e) { + CMS.getLogMessage("CMSGW_ERROR_LISTCERTS", e.toString()); + throw e; + } + return; + } + + private String insertCurrentTime(String filter) { + Date now = null; + StringBuffer newFilter = new StringBuffer(); + int k = 0; + int i = filter.indexOf(CURRENT_TIME, k); + + while (i > -1) { + if (now == null) + now = new Date(); + newFilter.append(filter.substring(k, i)); + newFilter.append(now.getTime()); + k = i + CURRENT_TIME.length(); + i = filter.indexOf(CURRENT_TIME, k); + } + if (k > 0) { + newFilter.append(filter.substring(k, filter.length())); + } + return newFilter.toString(); + } + + /** + * Fills cert record into argument block. + */ + private void fillRecordIntoArg(ICertRecord rec, IArgBlock rarg) + throws EBaseException { + + X509CertImpl xcert = rec.getCertificate(); + + if (xcert != null) { + fillX509RecordIntoArg(rec, rarg); + } + } + + private void fillX509RecordIntoArg(ICertRecord rec, IArgBlock rarg) + throws EBaseException { + + X509CertImpl cert = rec.getCertificate(); + + rarg.addIntegerValue("version", cert.getVersion()); + rarg.addStringValue("serialNumber", cert.getSerialNumber().toString(16)); + rarg.addStringValue("serialNumberDecimal", cert.getSerialNumber().toString()); + + String subject = (String) cert.getSubjectDN().toString(); + + if (subject.equals("")) { + rarg.addStringValue("subject", " "); + } else { + rarg.addStringValue("subject", subject); + + } + + rarg.addStringValue("type", "X.509"); + + try { + PublicKey pKey = cert.getPublicKey(); + X509Key key = null; + + if (pKey instanceof CertificateX509Key) { + CertificateX509Key certKey = (CertificateX509Key) pKey; + + key = (X509Key) certKey.get(CertificateX509Key.KEY); + } + if (pKey instanceof X509Key) { + key = (X509Key) pKey; + } + rarg.addStringValue("subjectPublicKeyAlgorithm", key.getAlgorithmId().getOID().toString()); + if (key.getAlgorithmId().toString().equalsIgnoreCase("RSA")) { + RSAPublicKey rsaKey = new RSAPublicKey(key.getEncoded()); + + rarg.addIntegerValue("subjectPublicKeyLength", rsaKey.getKeySize()); + } + } catch (Exception e) { + rarg.addStringValue("subjectPublicKeyAlgorithm", null); + rarg.addIntegerValue("subjectPublicKeyLength", 0); + } + + rarg.addLongValue("validNotBefore", cert.getNotBefore().getTime() / 1000); + rarg.addLongValue("validNotAfter", cert.getNotAfter().getTime() / 1000); + rarg.addStringValue("signatureAlgorithm", cert.getSigAlgOID()); + String issuedBy = rec.getIssuedBy(); + + if (issuedBy == null) + issuedBy = ""; + rarg.addStringValue("issuedBy", issuedBy); // cert.getIssuerDN().toString() + rarg.addLongValue("issuedOn", rec.getCreateTime().getTime() / 1000); + + rarg.addStringValue("revokedBy", + ((rec.getRevokedBy() == null) ? "" : rec.getRevokedBy())); + if (rec.getRevokedOn() == null) { + rarg.addStringValue("revokedOn", null); + } else { + rarg.addLongValue("revokedOn", rec.getRevokedOn().getTime() / 1000); + + IRevocationInfo revocationInfo = rec.getRevocationInfo(); + + if (revocationInfo != null) { + CRLExtensions crlExts = revocationInfo.getCRLEntryExtensions(); + + if (crlExts != null) { + Enumeration<Extension> enum1 = crlExts.getElements(); + int reason = 0; + + while (enum1.hasMoreElements()) { + Extension ext = enum1.nextElement(); + + if (ext instanceof CRLReasonExtension) { + reason = ((CRLReasonExtension) ext).getReason().toInt(); + break; + } + } + rarg.addIntegerValue("revocationReason", reason); + } + } + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/UpdateCRL.java b/base/common/src/com/netscape/cms/servlet/cert/UpdateCRL.java new file mode 100644 index 000000000..c0298d1e7 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/UpdateCRL.java @@ -0,0 +1,530 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.InvalidityDateExtension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +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.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.EErrorPublishCRL; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.ldap.ELdapException; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.ILdapRule; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Force the CRL to be updated now. + * + * @version $Revision$, $Date$ + */ +public class UpdateCRL extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -1182106454856991246L; + private final static String INFO = "UpdateCRL"; + private final static String TPL_FILE = "updateCRL.template"; + + private static Vector<String> mTesting = new Vector<String>(); + + private String mFormPath = null; + private ICertificateAuthority mCA = null; + + /** + * Constructs UpdateCRL servlet. + */ + public UpdateCRL() { + super(); + } + + /** + * Initializes the servlet. This servlet uses updateCRL.template + * to render the result + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mAuthority instanceof ICertificateAuthority) + mCA = (ICertificateAuthority) mAuthority; + + // override success to do output orw own template. + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param signatureAlgorithm the algorithm to use to sign the CRL + * <li>http.param waitForUpdate true/false - should the servlet wait until the CRL update is complete? + * <li>http.param clearCRLCache true/false - should the CRL cache cleared before the CRL is generated? + * <li>http.param crlIssuingPoint the CRL Issuing Point to Update + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("crl", true /* main action */); + } + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "update"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + if (statsSub != null) { + statsSub.endTiming("crl"); + } + return; + } + + EBaseException error = null; + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + if (statsSub != null) { + statsSub.endTiming("crl"); + } + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + String signatureAlgorithm = + req.getParameter("signatureAlgorithm"); + + process(argSet, header, req, resp, + signatureAlgorithm, locale[0]); + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", + e.toString())); + if (statsSub != null) { + statsSub.endTiming("crl"); + } + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + if (statsSub != null) { + statsSub.endTiming("crl"); + } + } + + private CRLExtensions crlEntryExtensions(String reason, String invalidity) { + CRLExtensions entryExts = new CRLExtensions(); + + CRLReasonExtension crlReasonExtn = null; + if (reason != null && reason.length() > 0) { + try { + RevocationReason revReason = RevocationReason.fromInt(Integer.parseInt(reason)); + if (revReason == null) + revReason = RevocationReason.UNSPECIFIED; + crlReasonExtn = new CRLReasonExtension(revReason); + } catch (Exception e) { + CMS.debug("Invalid revocation reason: " + reason); + } + } + + InvalidityDateExtension invalidityDateExtn = null; + if (invalidity != null && invalidity.length() > 0) { + long now = System.currentTimeMillis(); + Date invalidityDate = null; + try { + long backInTime = Long.parseLong(invalidity); + invalidityDate = new Date(now - (backInTime * 60000)); + } catch (Exception e) { + CMS.debug("Invalid invalidity time offset: " + invalidity); + } + if (invalidityDate != null) { + try { + invalidityDateExtn = new InvalidityDateExtension(invalidityDate); + } catch (Exception e) { + CMS.debug("Error creating invalidity extension: " + e); + } + } + } + + if (crlReasonExtn != null) { + try { + entryExts.set(crlReasonExtn.getName(), crlReasonExtn); + } catch (Exception e) { + CMS.debug("Error adding revocation reason extension to entry extensions: " + e); + } + } + + if (invalidityDateExtn != null) { + try { + entryExts.set(invalidityDateExtn.getName(), invalidityDateExtn); + } catch (Exception e) { + CMS.debug("Error adding invalidity date extension to entry extensions: " + e); + } + } + + return entryExts; + } + + private void addInfo(CMSTemplateParams argSet, ICRLIssuingPoint crlIssuingPoint, long cacheUpdate) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addLongValue("cacheUpdate", cacheUpdate); + + String crlNumbers = crlIssuingPoint.getCRLNumber().toString(); + BigInteger deltaNumber = crlIssuingPoint.getDeltaCRLNumber(); + String crlSizes = "" + crlIssuingPoint.getCRLSize(); + if (deltaNumber != null && deltaNumber.compareTo(BigInteger.ZERO) > 0) { + if (crlNumbers != null) + crlNumbers += ","; + if (crlNumbers != null) + crlNumbers += deltaNumber.toString(); + if (crlSizes != null) + crlSizes += "," + crlIssuingPoint.getDeltaCRLSize(); + } + rarg.addStringValue("crlNumbers", crlNumbers); + rarg.addStringValue("crlSizes", crlSizes); + + StringBuffer crlSplits = new StringBuffer(); + Vector<Long> splits = crlIssuingPoint.getSplitTimes(); + for (int i = 0; i < splits.size(); i++) { + crlSplits.append(splits.elementAt(i)); + if (i + 1 < splits.size()) + crlSplits.append(","); + } + rarg.addStringValue("crlSplits", crlSplits.toString()); + + argSet.addRepeatRecord(rarg); + } + + private void process(CMSTemplateParams argSet, IArgBlock header, + HttpServletRequest req, + HttpServletResponse resp, + String signatureAlgorithm, + Locale locale) + throws EBaseException { + long startTime = CMS.getCurrentDate().getTime(); + String waitForUpdate = + req.getParameter("waitForUpdate"); + String clearCache = + req.getParameter("clearCRLCache"); + String crlIssuingPointId = + req.getParameter("crlIssuingPoint"); + String test = req.getParameter("test"); + String add = req.getParameter("add"); + String from = req.getParameter("from"); + String by = req.getParameter("by"); + String reason = req.getParameter("reason"); + String invalidity = req.getParameter("invalidity"); + String results = req.getParameter("results"); + + if (crlIssuingPointId != null) { + Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = ips.nextElement(); + + if (crlIssuingPointId.equals(ip.getId())) { + break; + } + if (!ips.hasMoreElements()) + crlIssuingPointId = null; + } + } + if (crlIssuingPointId == null) { + crlIssuingPointId = ICertificateAuthority.PROP_MASTER_CRL; + } + + ICRLIssuingPoint crlIssuingPoint = + mCA.getCRLIssuingPoint(crlIssuingPointId); + header.addStringValue("crlIssuingPoint", crlIssuingPointId); + IPublisherProcessor lpm = mCA.getPublisherProcessor(); + + if (crlIssuingPoint != null) { + if (clearCache != null && clearCache.equals("true") && + crlIssuingPoint.isCRLGenerationEnabled() && + crlIssuingPoint.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_UPDATE_DONE && + crlIssuingPoint.isCRLIssuingPointInitialized() + == ICRLIssuingPoint.CRL_IP_INITIALIZED) { + crlIssuingPoint.clearCRLCache(); + } + if (waitForUpdate != null && waitForUpdate.equals("true") && + crlIssuingPoint.isCRLGenerationEnabled() && + crlIssuingPoint.isCRLUpdateInProgress() == ICRLIssuingPoint.CRL_UPDATE_DONE && + crlIssuingPoint.isCRLIssuingPointInitialized() + == ICRLIssuingPoint.CRL_IP_INITIALIZED) { + if (test != null && test.equals("true") && + crlIssuingPoint.isCRLCacheTestingEnabled() && + (!mTesting.contains(crlIssuingPointId))) { + CMS.debug("CRL test started."); + mTesting.add(crlIssuingPointId); + BigInteger addLen = null; + BigInteger startFrom = null; + if (add != null && add.length() > 0 && + from != null && from.length() > 0) { + try { + addLen = new BigInteger(add); + startFrom = new BigInteger(from); + } catch (Exception e) { + } + } + if (addLen != null && startFrom != null) { + Date revocationDate = CMS.getCurrentDate(); + String err = null; + + CRLExtensions entryExts = crlEntryExtensions(reason, invalidity); + + BigInteger serialNumber = startFrom; + BigInteger counter = addLen; + BigInteger stepBy = null; + if (by != null && by.length() > 0) { + try { + stepBy = new BigInteger(by); + } catch (Exception e) { + } + } + + long t1 = System.currentTimeMillis(); + long t2 = 0; + + while (counter.compareTo(BigInteger.ZERO) > 0) { + RevokedCertImpl revokedCert = + new RevokedCertImpl(serialNumber, revocationDate, entryExts); + crlIssuingPoint.addRevokedCert(serialNumber, revokedCert); + serialNumber = serialNumber.add(BigInteger.ONE); + counter = counter.subtract(BigInteger.ONE); + + if ((counter.compareTo(BigInteger.ZERO) == 0) || + (stepBy != null && ((counter.mod(stepBy)).compareTo(BigInteger.ZERO) == 0))) { + t2 = System.currentTimeMillis(); + long t0 = t2 - t1; + t1 = t2; + try { + if (signatureAlgorithm != null) { + crlIssuingPoint.updateCRLNow(signatureAlgorithm); + } else { + crlIssuingPoint.updateCRLNow(); + } + } catch (Throwable e) { + counter = BigInteger.ZERO; + err = e.toString(); + } + if (results != null && results.equals("1")) { + addInfo(argSet, crlIssuingPoint, t0); + } + } + } + if (err != null) { + header.addStringValue("crlUpdate", "Failure"); + header.addStringValue("error", err); + } else { + header.addStringValue("crlUpdate", "Success"); + } + } else { + CMS.debug("CRL test error: missing parameters."); + header.addStringValue("crlUpdate", "missingParameters"); + } + + mTesting.remove(crlIssuingPointId); + CMS.debug("CRL test finished."); + } else if (test != null && test.equals("true") && + crlIssuingPoint.isCRLCacheTestingEnabled() && + mTesting.contains(crlIssuingPointId)) { + header.addStringValue("crlUpdate", "testingInProgress"); + } else if (test != null && test.equals("true") && + (!crlIssuingPoint.isCRLCacheTestingEnabled())) { + header.addStringValue("crlUpdate", "testingNotEnabled"); + } else { + try { + EBaseException publishError = null; + + try { + long now1 = System.currentTimeMillis(); + + if (signatureAlgorithm != null) { + crlIssuingPoint.updateCRLNow(signatureAlgorithm); + } else { + crlIssuingPoint.updateCRLNow(); + } + + long now2 = System.currentTimeMillis(); + + header.addStringValue("time", "" + (now2 - now1)); + } catch (EErrorPublishCRL e) { + publishError = e; + } + + if (lpm != null && lpm.enabled()) { + Enumeration<ILdapRule> rules = lpm.getRules(IPublisherProcessor.PROP_LOCAL_CRL); + if (rules != null && rules.hasMoreElements()) { + if (publishError != null) { + header.addStringValue("crlPublished", "Failure"); + header.addStringValue("error", publishError.toString(locale)); + } else { + header.addStringValue("crlPublished", "Success"); + } + } + } + + // for audit log + SessionContext sContext = SessionContext.getContext(); + String agentId = (String) sContext.get(SessionContext.USER_ID); + IAuthToken authToken = (IAuthToken) sContext.get(SessionContext.AUTH_TOKEN); + String authMgr = AuditFormat.NOAUTH; + + if (authToken != null) { + authMgr = authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } + long endTime = CMS.getCurrentDate().getTime(); + + if (crlIssuingPoint.getNextUpdate() != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.CRLUPDATEFORMAT, + new Object[] { + AuditFormat.FROMAGENT + " agentID: " + agentId, + authMgr, + "completed", + crlIssuingPoint.getId(), + crlIssuingPoint.getCRLNumber(), + crlIssuingPoint.getLastUpdate(), + crlIssuingPoint.getNextUpdate(), + Long.toString(crlIssuingPoint.getCRLSize()) + + " time: " + (endTime - startTime) } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.CRLUPDATEFORMAT, + new Object[] { + AuditFormat.FROMAGENT + " agentID: " + agentId, + authMgr, + "completed", + crlIssuingPoint.getId(), + crlIssuingPoint.getCRLNumber(), + crlIssuingPoint.getLastUpdate(), + "not set", + Long.toString(crlIssuingPoint.getCRLSize()) + + " time: " + (endTime - startTime) } + ); + } + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_UPDATE_CRL", e.toString())); + if ((lpm != null) && lpm.enabled() && (e instanceof ELdapException)) { + header.addStringValue("crlPublished", "Failure"); + header.addStringValue("error", e.toString(locale)); + } else { + throw e; + } + } + } + } else { + if (crlIssuingPoint.isCRLIssuingPointInitialized() != ICRLIssuingPoint.CRL_IP_INITIALIZED) { + header.addStringValue("crlUpdate", "notInitialized"); + } else if (crlIssuingPoint.isCRLUpdateInProgress() + != ICRLIssuingPoint.CRL_UPDATE_DONE || + crlIssuingPoint.isManualUpdateSet()) { + header.addStringValue("crlUpdate", "inProgress"); + } else if (!crlIssuingPoint.isCRLGenerationEnabled()) { + header.addStringValue("crlUpdate", "Disabled"); + } else { + crlIssuingPoint.setManualUpdate(signatureAlgorithm); + header.addStringValue("crlUpdate", "Scheduled"); + } + } + } + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/UpdateDir.java b/base/common/src/com/netscape/cms/servlet/cert/UpdateDir.java new file mode 100644 index 000000000..707e7ff5f --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/UpdateDir.java @@ -0,0 +1,747 @@ +// --- 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.cert; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CRLImpl; +import netscape.security.x509.X509CertImpl; + +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.base.IArgBlock; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICRLIssuingPoint; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.dbs.crldb.ICRLRepository; +import com.netscape.certsrv.ldap.ELdapException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Update the configured LDAP server with specified objects + * + * @version $Revision$, $Date$ + */ +public class UpdateDir extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 3063889978908136789L; + private final static String INFO = "UpdateDir"; + private final static String TPL_FILE = "updateDir.template"; + private final static int UPDATE_ALL = 0; + private final static int UPDATE_CRL = 1; + private final static int UPDATE_CA = 2; + private final static int UPDATE_VALID = 3; + private final static int VALID_FROM = 4; + private final static int VALID_TO = 5; + private final static int UPDATE_EXPIRED = 6; + private final static int EXPIRED_FROM = 7; + private final static int EXPIRED_TO = 8; + private final static int UPDATE_REVOKED = 9; + private final static int REVOKED_FROM = 10; + private final static int REVOKED_TO = 11; + private final static int CHECK_FLAG = 12; + private final static String[] updateName = + { "updateAll", "updateCRL", "updateCA", + "updateValid", "validFrom", "validTo", + "updateExpired", "expiredFrom", "expiredTo", + "updateRevoked", "revokedFrom", "revokedTo", + "checkFlag" }; + + private String mFormPath = null; + private ICertificateAuthority mCA = null; + private IPublisherProcessor mPublisherProcessor = null; + private ICRLRepository mCRLRepository = null; + private boolean mClonedCA = false; + + /** + * Constructs UpdateDir servlet. + */ + public UpdateDir() { + super(); + } + + /** + * Initialize the servlet. This servlet uses the template + * 'updateDir.template' to render the response + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + if (mAuthority != null) { + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + if (mAuthority instanceof ICertificateAuthority) { + mCA = (ICertificateAuthority) mAuthority; + mPublisherProcessor = mCA.getPublisherProcessor(); + mCRLRepository = mCA.getCRLRepository(); + } + + // override success to do output orw own template. + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) { + mFormPath = mOutputTemplatePath; + } + } + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "update"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + EBaseException error = null; + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + String crlIssuingPointId = req.getParameter("crlIssuingPoint"); + + if (mPublisherProcessor == null || + !mPublisherProcessor.enabled()) + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_PUB_MODULE")); + + String[] updateValue = new String[updateName.length]; + + for (int i = 0; i < updateName.length; i++) { + updateValue[i] = req.getParameter(updateName[i]); + } + + String masterHost = CMS.getConfigStore().getString("master.ca.agent.host", ""); + String masterPort = CMS.getConfigStore().getString("master.ca.agent.port", ""); + if (masterHost != null && masterHost.length() > 0 && + masterPort != null && masterPort.length() > 0) { + mClonedCA = true; + } + + process(argSet, header, req, resp, crlIssuingPointId, updateValue, locale[0]); + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + private void updateCRLIssuingPoint( + IArgBlock header, + String crlIssuingPointId, + ICRLIssuingPoint crlIssuingPoint, + Locale locale) { + SessionContext sc = SessionContext.getContext(); + + sc.put(ICRLIssuingPoint.SC_ISSUING_POINT_ID, crlIssuingPointId); + sc.put(ICRLIssuingPoint.SC_IS_DELTA_CRL, "false"); + ICRLIssuingPointRecord crlRecord = null; + + try { + if (mCRLRepository != null) { + crlRecord = (ICRLIssuingPointRecord) mCRLRepository.readCRLIssuingPointRecord(crlIssuingPointId); + } + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_GET_CRL_RECORD", e.toString())); + } + + if (crlRecord == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", crlIssuingPointId)); + header.addStringValue("crlPublished", "Failure"); + header.addStringValue("crlError", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString()); + } else { + String publishDN = (crlIssuingPoint != null) ? crlIssuingPoint.getPublishDN() : null; + byte[] crlbytes = crlRecord.getCRL(); + + if (crlbytes == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CRL_NOT_YET_UPDATED_1", "")); + header.addStringValue("crlPublished", "Failure"); + header.addStringValue("crlError", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_CRL_NOT_YET_UPDATED")).toString()); + } else { + X509CRLImpl crl = null; + + try { + crl = new X509CRLImpl(crlbytes); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_CRL", e.toString())); + } + + if (crl == null) { + header.addStringValue("crlPublished", "Failure"); + header.addStringValue("crlError", + new ECMSGWException(CMS.getUserMessage(locale, "CMS_GW_DECODE_CRL_FAILED")).toString()); + } else { + try { + if (publishDN != null) { + mPublisherProcessor.publishCRL(publishDN, crl); + } else { + mPublisherProcessor.publishCRL(crl, crlIssuingPointId); + } + header.addStringValue("crlPublished", "Success"); + } catch (ELdapException e) { + header.addStringValue("crlPublished", "Failure"); + header.addStringValue("crlError", e.toString(locale)); + log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR_PUBLISH_CRL", e.toString())); + } + } + } + + sc.put(ICRLIssuingPoint.SC_IS_DELTA_CRL, "true"); + // handle delta CRL if any + byte[] deltaCrlBytes = crlRecord.getDeltaCRL(); + + if (deltaCrlBytes != null) { + X509CRLImpl deltaCrl = null; + + try { + deltaCrl = new X509CRLImpl(deltaCrlBytes); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_DECODE_DELTA_CRL", e.toString())); + } + + boolean goodDelta = false; + if (mClonedCA) { + BigInteger crlNumber = crlRecord.getCRLNumber(); + BigInteger deltaNumber = crlRecord.getDeltaCRLNumber(); + Long deltaCRLSize = crlRecord.getDeltaCRLSize(); + if (deltaCRLSize != null && deltaCRLSize.longValue() > -1 && + crlNumber != null && deltaNumber != null && + deltaNumber.compareTo(crlNumber) >= 0) { + goodDelta = true; + } + } + + if (deltaCrl != null && ((mClonedCA && goodDelta) || + (crlIssuingPoint != null && + crlIssuingPoint.isThisCurrentDeltaCRL(deltaCrl)))) { + try { + if (publishDN != null) { + mPublisherProcessor.publishCRL(publishDN, deltaCrl); + } else { + mPublisherProcessor.publishCRL(deltaCrl, crlIssuingPointId); + } + } catch (ELdapException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERR_PUBLISH_DELTA_CRL", e.toString())); + } + } + } + } // if + } + + private void process(CMSTemplateParams argSet, IArgBlock header, + HttpServletRequest req, + HttpServletResponse resp, + String crlIssuingPointId, + String[] updateValue, + Locale locale) + throws EBaseException { + // all or crl + if ((updateValue[UPDATE_ALL] != null && + updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) || + (updateValue[UPDATE_CRL] != null && + updateValue[UPDATE_CRL].equalsIgnoreCase("yes"))) { + // check if received issuing point ID is known to the server + if (crlIssuingPointId != null) { + Enumeration<ICRLIssuingPoint> ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = ips.nextElement(); + + if (crlIssuingPointId.equals(ip.getId())) { + break; + } + if (!ips.hasMoreElements()) + crlIssuingPointId = null; + } + } + if (crlIssuingPointId == null) { + // publish all issuing points + if (mClonedCA && mCRLRepository != null) { + Vector<String> ipNames = mCRLRepository.getIssuingPointsNames(); + if (ipNames != null && ipNames.size() > 0) { + for (int i = 0; i < ipNames.size(); i++) { + String ipName = ipNames.elementAt(i); + + updateCRLIssuingPoint(header, ipName, null, locale); + } + } + } else { + Enumeration<ICRLIssuingPoint> oips = mCA.getCRLIssuingPoints(); + + while (oips.hasMoreElements()) { + ICRLIssuingPoint oip = oips.nextElement(); + + updateCRLIssuingPoint(header, oip.getId(), oip, locale); + } + } + } else { + ICRLIssuingPoint crlIssuingPoint = + mCA.getCRLIssuingPoint(crlIssuingPointId); + + updateCRLIssuingPoint(header, crlIssuingPointId, + crlIssuingPoint, locale); + } + } + + ICertificateRepository certificateRepository = (ICertificateRepository) mCA.getCertificateRepository(); + + // all or ca + if ((updateValue[UPDATE_ALL] != null && + updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) || + (updateValue[UPDATE_CA] != null && + updateValue[UPDATE_CA].equalsIgnoreCase("yes"))) { + X509CertImpl caCert = mCA.getSigningUnit().getCertImpl(); + + try { + mPublisherProcessor.publishCACert(caCert); + header.addStringValue("caCertPublished", "Success"); + } catch (ELdapException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("LDAP_ERROR_PUBLISH_CACERT_1", + caCert.getSerialNumber().toString(16), e.toString())); + header.addStringValue("caCertPublished", "Failure"); + header.addStringValue("caCertError", e.toString(locale)); + } + } + + // all or valid + if ((updateValue[UPDATE_ALL] != null && + updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) || + (updateValue[UPDATE_VALID] != null && + updateValue[UPDATE_VALID].equalsIgnoreCase("yes"))) { + if (certificateRepository != null) { + if (updateValue[VALID_FROM].startsWith("0x")) { + updateValue[VALID_FROM] = hexToDecimal(updateValue[VALID_FROM]); + } + if (updateValue[VALID_TO].startsWith("0x")) { + updateValue[VALID_TO] = hexToDecimal(updateValue[VALID_TO]); + } + Enumeration<ICertRecord> validCerts = null; + + if (updateValue[CHECK_FLAG] != null && + updateValue[CHECK_FLAG].equalsIgnoreCase("yes")) { + validCerts = + certificateRepository.getValidNotPublishedCertificates( + updateValue[VALID_FROM], + updateValue[VALID_TO]); + } else { + validCerts = + certificateRepository.getValidCertificates( + updateValue[VALID_FROM], + updateValue[VALID_TO]); + } + int i = 0; + int l = 0; + String validCertsError = ""; + + if (validCerts != null) { + while (validCerts.hasMoreElements()) { + ICertRecord certRecord = + validCerts.nextElement(); + //X509CertImpl cert = certRecord.getCertificate(); + X509CertImpl cert = null; + Object o = certRecord.getCertificate(); + + if (o instanceof X509CertImpl) + cert = (X509CertImpl) o; + + MetaInfo metaInfo = null; + String ridString = null; + + metaInfo = (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO); + if (metaInfo == null) { + // ca's self signed signing cert and + // server cert has no related request and + // have no metaInfo + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAIL_GET_ICERT_RECORD", + cert.getSerialNumber().toString(16))); + } else { + ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + } + + IRequest r = null; + + if (ridString != null) { + RequestId rid = new RequestId(ridString); + + r = mCA.getRequestQueue().findRequest(rid); + } + + try { + l++; + SessionContext sc = SessionContext.getContext(); + + if (r == null) { + if (CMS.isEncryptionCert(cert)) + sc.put((Object) "isEncryptionCert", (Object) "true"); + else + sc.put((Object) "isEncryptionCert", (Object) "false"); + mPublisherProcessor.publishCert(cert, null); + } else { + if (CMS.isEncryptionCert(cert)) + r.setExtData("isEncryptionCert", "true"); + else + r.setExtData("isEncryptionCert", "false"); + mPublisherProcessor.publishCert(cert, r); + } + i++; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAIL_PUBLISH_CERT", + certRecord.getSerialNumber().toString(16), + e.toString())); + validCertsError += + "Failed to publish certificate: 0x" + + certRecord.getSerialNumber().toString(16) + + ".\n <BR> "; + } + } + } + if (i > 0 && i == l) { + header.addStringValue("validCertsPublished", + "Success"); + if (i == 1) + header.addStringValue("validCertsError", i + + " valid certificate is published in the directory."); + else + header.addStringValue("validCertsError", i + + " valid certificates are published in the directory."); + } else { + if (l == 0) { + header.addStringValue("validCertsPublished", "No"); + } else { + header.addStringValue("validCertsPublished", "Failure"); + header.addStringValue("validCertsError", + validCertsError); + } + } + } else { + header.addStringValue("validCertsPublished", "Failure"); + header.addStringValue("validCertsError", "Certificate repository is unavailable."); + } + } + + // all or expired + if ((updateValue[UPDATE_ALL] != null && + updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) || + (updateValue[UPDATE_EXPIRED] != null && + updateValue[UPDATE_EXPIRED].equalsIgnoreCase("yes"))) { + if (certificateRepository != null) { + if (updateValue[EXPIRED_FROM].startsWith("0x")) { + updateValue[EXPIRED_FROM] = hexToDecimal(updateValue[EXPIRED_FROM]); + } + if (updateValue[EXPIRED_TO].startsWith("0x")) { + updateValue[EXPIRED_TO] = hexToDecimal(updateValue[EXPIRED_TO]); + } + Enumeration<ICertRecord> expiredCerts = null; + + if (updateValue[CHECK_FLAG] != null && + updateValue[CHECK_FLAG].equalsIgnoreCase("yes")) { + expiredCerts = + certificateRepository.getExpiredPublishedCertificates( + updateValue[EXPIRED_FROM], + updateValue[EXPIRED_TO]); + } else { + expiredCerts = + certificateRepository.getExpiredCertificates( + updateValue[EXPIRED_FROM], + updateValue[EXPIRED_TO]); + } + int i = 0; + int l = 0; + StringBuffer expiredCertsError = new StringBuffer(); + + if (expiredCerts != null) { + while (expiredCerts.hasMoreElements()) { + ICertRecord certRecord = expiredCerts.nextElement(); + //X509CertImpl cert = certRecord.getCertificate(); + X509CertImpl cert = null; + Object o = certRecord.getCertificate(); + + if (o instanceof X509CertImpl) + cert = (X509CertImpl) o; + + MetaInfo metaInfo = null; + String ridString = null; + + metaInfo = (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO); + if (metaInfo == null) { + // ca's self signed signing cert and + // server cert has no related request and + // have no metaInfo + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAIL_GET_ICERT_RECORD", + cert.getSerialNumber().toString(16))); + } else { + ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + } + + IRequest r = null; + + if (ridString != null) { + RequestId rid = new RequestId(ridString); + + r = mCA.getRequestQueue().findRequest(rid); + } + + try { + l++; + if (r == null) { + mPublisherProcessor.unpublishCert(cert, null); + } else { + mPublisherProcessor.unpublishCert(cert, r); + } + i++; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("LDAP_ERROR_UNPUBLISH_CERT", + certRecord.getSerialNumber().toString(16), + e.toString())); + expiredCertsError.append( + "Failed to unpublish certificate: 0x"); + expiredCertsError.append( + certRecord.getSerialNumber().toString(16)); + expiredCertsError.append( + ".\n <BR> "); + } + } + } + if (i > 0 && i == l) { + header.addStringValue("expiredCertsUnpublished", "Success"); + if (i == 1) + header.addStringValue("expiredCertsError", i + + " expired certificate is unpublished in the directory."); + else + header.addStringValue("expiredCertsError", i + + " expired certificates are unpublished in the directory."); + } else { + if (l == 0) { + header.addStringValue("expiredCertsUnpublished", "No"); + } else { + header.addStringValue("expiredCertsUnpublished", "Failure"); + header.addStringValue("expiredCertsError", + expiredCertsError.toString()); + } + } + } else { + header.addStringValue("expiredCertsUnpublished", "Failure"); + header.addStringValue("expiredCertsError", "Certificate repository is unavailable."); + } + } + + // all or revoked + if ((updateValue[UPDATE_ALL] != null && + updateValue[UPDATE_ALL].equalsIgnoreCase("yes")) || + (updateValue[UPDATE_REVOKED] != null && + updateValue[UPDATE_REVOKED].equalsIgnoreCase("yes"))) { + if (certificateRepository != null) { + if (updateValue[REVOKED_FROM].startsWith("0x")) { + updateValue[REVOKED_FROM] = hexToDecimal(updateValue[REVOKED_FROM]); + } + if (updateValue[REVOKED_TO].startsWith("0x")) { + updateValue[REVOKED_TO] = hexToDecimal(updateValue[REVOKED_TO]); + } + Enumeration<ICertRecord> revokedCerts = null; + + if (updateValue[CHECK_FLAG] != null && + updateValue[CHECK_FLAG].equalsIgnoreCase("yes")) { + revokedCerts = + certificateRepository.getRevokedPublishedCertificates( + updateValue[REVOKED_FROM], + updateValue[REVOKED_TO]); + } else { + revokedCerts = + certificateRepository.getRevokedCertificates( + updateValue[REVOKED_FROM], + updateValue[REVOKED_TO]); + } + int i = 0; + int l = 0; + String revokedCertsError = ""; + + if (revokedCerts != null) { + while (revokedCerts.hasMoreElements()) { + ICertRecord certRecord = revokedCerts.nextElement(); + //X509CertImpl cert = certRecord.getCertificate(); + X509CertImpl cert = null; + Object o = certRecord.getCertificate(); + + if (o instanceof X509CertImpl) + cert = (X509CertImpl) o; + + MetaInfo metaInfo = null; + String ridString = null; + + metaInfo = (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO); + if (metaInfo == null) { + // ca's self signed signing cert and + // server cert has no related request and + // have no metaInfo + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAIL_GET_ICERT_RECORD", + cert.getSerialNumber().toString(16))); + } else { + ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + } + + IRequest r = null; + + if (ridString != null) { + RequestId rid = new RequestId(ridString); + + r = mCA.getRequestQueue().findRequest(rid); + } + + try { + l++; + if (r == null) { + mPublisherProcessor.unpublishCert(cert, null); + } else { + mPublisherProcessor.unpublishCert(cert, r); + } + i++; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("LDAP_ERROR_UNPUBLISH_CERT", + certRecord.getSerialNumber().toString(16), + e.toString())); + revokedCertsError += + "Failed to unpublish certificate: 0x" + + certRecord.getSerialNumber().toString(16) + + ".\n <BR> "; + } + } + } + if (i > 0 && i == l) { + header.addStringValue("revokedCertsUnpublished", "Success"); + if (i == 1) + header.addStringValue("revokedCertsError", i + + " revoked certificate is unpublished in the directory."); + else + header.addStringValue("revokedCertsError", i + + " revoked certificates are unpublished in the directory."); + } else { + if (l == 0) { + header.addStringValue("revokedCertsUnpublished", "No"); + } else { + header.addStringValue("revokedCertsUnpublished", "Failure"); + header.addStringValue("revokedCertsError", + revokedCertsError); + } + } + } else { + header.addStringValue("revokedCertsUnpublished", "Failure"); + header.addStringValue("revokedCertsError", "Certificate repository is unavailable."); + } + } + + return; + } + + private String hexToDecimal(String hex) { + String newHex = hex.substring(2); + BigInteger bi = new BigInteger(newHex, 16); + + return bi.toString(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/model/CertificateData.java b/base/common/src/com/netscape/cms/servlet/cert/model/CertificateData.java new file mode 100644 index 000000000..14c537098 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/model/CertificateData.java @@ -0,0 +1,53 @@ +// --- 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) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.cert.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * @author alee + * + */ +@XmlRootElement(name = "CertificateData") +@XmlAccessorType(XmlAccessType.FIELD) +public class CertificateData { + @XmlElement + private String b64; + + public CertificateData() { + // required for jaxb + } + + /** + * @return the b64 + */ + public String getB64() { + return b64; + } + + /** + * @param b64 the b64 to set + */ + public void setB64(String b64) { + this.b64 = b64; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java b/base/common/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java new file mode 100644 index 000000000..90a48cb4e --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java @@ -0,0 +1,2135 @@ +// --- 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.cert.scep; + +import java.io.ByteArrayInputStream; +import java.io.FileOutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Random; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.security.pkcs.PKCS10; +import netscape.security.pkcs.PKCS10Attribute; +import netscape.security.pkcs.PKCS10Attributes; +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.AVA; +import netscape.security.x509.CertAttrSet; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.DNSName; +import netscape.security.x509.Extension; +import netscape.security.x509.GeneralName; +import netscape.security.x509.GeneralNameInterface; +import netscape.security.x509.GeneralNames; +import netscape.security.x509.IPAddressName; +import netscape.security.x509.KeyUsageExtension; +import netscape.security.x509.OIDMap; +import netscape.security.x509.RDN; +import netscape.security.x509.SubjectAlternativeNameExtension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X500NameAttrMap; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.NoSuchTokenException; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.BIT_STRING; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.crypto.Cipher; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.EncryptionAlgorithm; +import org.mozilla.jss.crypto.IVParameterSpec; +import org.mozilla.jss.crypto.KeyGenAlgorithm; +import org.mozilla.jss.crypto.KeyGenerator; +import org.mozilla.jss.crypto.KeyWrapAlgorithm; +import org.mozilla.jss.crypto.KeyWrapper; +import org.mozilla.jss.crypto.ObjectNotFoundException; +import org.mozilla.jss.crypto.SymmetricKey; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.pkcs7.IssuerAndSerialNumber; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.util.IncorrectPasswordException; +import org.mozilla.jss.util.PasswordCallback; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthCredentials; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.EInvalidCredentials; +import com.netscape.certsrv.authentication.EMissingCredential; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.ldap.ILdapConnFactory; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileContext; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.profile.SSLClientCertProvider; +import com.netscape.cmsutil.scep.CRSPKIMessage; +import com.netscape.cmsutil.util.Utils; + +/** + * This servlet deals with PKCS#10-based certificate requests from + * CRS, now called SCEP, and defined at: + * http://search.ietf.org/internet-drafts/draft-nourse-scep-02.txt + * + * The router is hardcoded to look for the http://host:80/cgi-bin/pkiclient.exe + * + * The HTTP parameters are 'operation' and 'message' + * operation can be either 'GetCACert' or 'PKIOperation' + * + * @version $Revision$, $Date$ + */ +public class CRSEnrollment extends HttpServlet { + /** + * + */ + private static final long serialVersionUID = 8483002540957382369L; + protected IProfileSubsystem mProfileSubsystem = null; + protected String mProfileId = null; + protected ICertAuthority mAuthority; + protected IConfigStore mConfig = null; + protected IAuthSubsystem mAuthSubsystem; + protected String mAppendDN = null; + protected String mEntryObjectclass = null; + protected boolean mCreateEntry = false; + protected boolean mFlattenDN = false; + + private String mAuthManagerName; + private String mSubstoreName; + private boolean mEnabled = false; + private boolean mUseCA = true; + private String mNickname = null; + private String mTokenName = ""; + private String mHashAlgorithm = "SHA1"; + private String mHashAlgorithmList = null; + private String[] mAllowedHashAlgorithm; + private String mConfiguredEncryptionAlgorithm = "DES3"; + private String mEncryptionAlgorithm = "DES3"; + private String mEncryptionAlgorithmList = null; + private String[] mAllowedEncryptionAlgorithm; + private Random mRandom = null; + private int mNonceSizeLimit = 0; + protected ILogger mLogger = CMS.getLogger(); + private ICertificateAuthority ca; + /* for hashing challenge password */ + protected MessageDigest mSHADigest = null; + + private static final String PROP_SUBSTORENAME = "substorename"; + private static final String PROP_AUTHORITY = "authority"; + private static final String PROP_CRS = "crs"; + private static final String PROP_CRSCA = "casubsystem"; + private static final String PROP_CRSAUTHMGR = "authName"; + private static final String PROP_APPENDDN = "appendDN"; + private static final String PROP_CREATEENTRY = "createEntry"; + private static final String PROP_FLATTENDN = "flattenDN"; + private static final String PROP_ENTRYOC = "entryObjectclass"; + + // URL parameters + private static final String URL_OPERATION = "operation"; + private static final String URL_MESSAGE = "message"; + + // possible values for 'operation' + private static final String OP_GETCACERT = "GetCACert"; + private static final String OP_PKIOPERATION = "PKIOperation"; + + public static final String AUTH_PASSWORD = "pwd"; + + public static final String AUTH_CREDS = "AuthCreds"; + public static final String AUTH_TOKEN = "AuthToken"; + public static final String AUTH_FAILED = "AuthFailed"; + + public static final String SANE_DNSNAME = "DNSName"; + public static final String SANE_IPADDRESS = "IPAddress"; + + public static final String CERTINFO = "CertInfo"; + public static final String SUBJECTNAME = "SubjectName"; + + public static ObjectIdentifier OID_UNSTRUCTUREDNAME = null; + public static ObjectIdentifier OID_UNSTRUCTUREDADDRESS = null; + public static ObjectIdentifier OID_SERIALNUMBER = null; + + public CRSEnrollment() { + } + + public static Hashtable<String, String> toHashtable(HttpServletRequest req) { + Hashtable<String, String> httpReqHash = new Hashtable<String, String>(); + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + httpReqHash.put(name, req.getParameter(name)); + } + return httpReqHash; + } + + public void init(ServletConfig sc) { + // Find the CertificateAuthority we should use for CRS. + String crsCA = sc.getInitParameter(PROP_AUTHORITY); + if (crsCA == null) + crsCA = "ca"; + mAuthority = (ICertAuthority) CMS.getSubsystem(crsCA); + ca = (ICertificateAuthority) mAuthority; + + if (mAuthority == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CANT_FIND_AUTHORITY", crsCA)); + } + + try { + if (mAuthority instanceof ISubsystem) { + IConfigStore authorityConfig = ((ISubsystem) mAuthority).getConfigStore(); + IConfigStore scepConfig = authorityConfig.getSubStore("scep"); + mEnabled = scepConfig.getBoolean("enable", false); + mHashAlgorithm = scepConfig.getString("hashAlgorithm", "SHA1"); + mConfiguredEncryptionAlgorithm = scepConfig.getString("encryptionAlgorithm", "DES3"); + mNonceSizeLimit = scepConfig.getInteger("nonceSizeLimit", 0); + mHashAlgorithmList = scepConfig.getString("allowedHashAlgorithms", "SHA1,SHA256,SHA512"); + mAllowedHashAlgorithm = mHashAlgorithmList.split(","); + mEncryptionAlgorithmList = scepConfig.getString("allowedEncryptionAlgorithms", "DES3"); + mAllowedEncryptionAlgorithm = mEncryptionAlgorithmList.split(","); + mNickname = scepConfig.getString("nickname", ca.getNickname()); + if (mNickname.equals(ca.getNickname())) { + mTokenName = ca.getSigningUnit().getTokenName(); + } else { + mTokenName = scepConfig.getString("tokenname", ""); + mUseCA = false; + } + if (!(mTokenName.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN) || + mTokenName.equalsIgnoreCase("Internal Key Storage Token") || mTokenName.length() == 0)) { + int i = mNickname.indexOf(':'); + if (!((i > -1) && (mTokenName.length() == i) && (mNickname.startsWith(mTokenName)))) { + mNickname = mTokenName + ":" + mNickname; + } + } + } + } catch (EBaseException e) { + CMS.debug("CRSEnrollment: init: EBaseException: " + e); + } + mEncryptionAlgorithm = mConfiguredEncryptionAlgorithm; + CMS.debug("CRSEnrollment: init: SCEP support is " + ((mEnabled) ? "enabled" : "disabled") + "."); + CMS.debug("CRSEnrollment: init: SCEP nickname: " + mNickname); + CMS.debug("CRSEnrollment: init: CA nickname: " + ca.getNickname()); + CMS.debug("CRSEnrollment: init: Token name: " + mTokenName); + CMS.debug("CRSEnrollment: init: Is SCEP using CA keys: " + mUseCA); + CMS.debug("CRSEnrollment: init: mNonceSizeLimit: " + mNonceSizeLimit); + CMS.debug("CRSEnrollment: init: mHashAlgorithm: " + mHashAlgorithm); + CMS.debug("CRSEnrollment: init: mHashAlgorithmList: " + mHashAlgorithmList); + for (int i = 0; i < mAllowedHashAlgorithm.length; i++) { + mAllowedHashAlgorithm[i] = mAllowedHashAlgorithm[i].trim(); + CMS.debug("CRSEnrollment: init: mAllowedHashAlgorithm[" + i + "]=" + mAllowedHashAlgorithm[i]); + } + CMS.debug("CRSEnrollment: init: mEncryptionAlgorithm: " + mEncryptionAlgorithm); + CMS.debug("CRSEnrollment: init: mEncryptionAlgorithmList: " + mEncryptionAlgorithmList); + for (int i = 0; i < mAllowedEncryptionAlgorithm.length; i++) { + mAllowedEncryptionAlgorithm[i] = mAllowedEncryptionAlgorithm[i].trim(); + CMS.debug("CRSEnrollment: init: mAllowedEncryptionAlgorithm[" + i + "]=" + mAllowedEncryptionAlgorithm[i]); + } + + try { + mProfileSubsystem = (IProfileSubsystem) CMS.getSubsystem("profile"); + mProfileId = sc.getInitParameter("profileId"); + CMS.debug("CRSEnrollment: init: mProfileId=" + mProfileId); + + mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + mAuthManagerName = sc.getInitParameter(PROP_CRSAUTHMGR); + mAppendDN = sc.getInitParameter(PROP_APPENDDN); + String tmp = sc.getInitParameter(PROP_CREATEENTRY); + if (tmp != null && tmp.trim().equalsIgnoreCase("true")) + mCreateEntry = true; + else + mCreateEntry = false; + tmp = sc.getInitParameter(PROP_FLATTENDN); + if (tmp != null && tmp.trim().equalsIgnoreCase("true")) + mFlattenDN = true; + else + mFlattenDN = false; + mEntryObjectclass = sc.getInitParameter(PROP_ENTRYOC); + if (mEntryObjectclass == null) + mEntryObjectclass = "cep"; + mSubstoreName = sc.getInitParameter(PROP_SUBSTORENAME); + if (mSubstoreName == null) + mSubstoreName = "default"; + } catch (Exception e) { + } + + OID_UNSTRUCTUREDNAME = X500NameAttrMap.getDefault().getOid("UNSTRUCTUREDNAME"); + OID_UNSTRUCTUREDADDRESS = X500NameAttrMap.getDefault().getOid("UNSTRUCTUREDADDRESS"); + OID_SERIALNUMBER = X500NameAttrMap.getDefault().getOid("SERIALNUMBER"); + + try { + mSHADigest = MessageDigest.getInstance("SHA1"); + } catch (NoSuchAlgorithmException e) { + } + + mRandom = new Random(); + } + + /** + * + * Service a CRS Request. It all starts here. This is where the message from the + * router is processed + * + * @param httpReq The HttpServletRequest. + * @param httpResp The HttpServletResponse. + * + */ + public void service(HttpServletRequest httpReq, + HttpServletResponse httpResp) + throws ServletException { + boolean running_state = CMS.isInRunningState(); + if (!running_state) + throw new ServletException( + "CMS server is not ready to serve."); + + String operation = null; + String message = null; + mEncryptionAlgorithm = mConfiguredEncryptionAlgorithm; + + // Parse the URL from the HTTP Request. Split it up into + // a structure which enables us to read the form elements + IArgBlock input = CMS.createArgBlock(toHashtable(httpReq)); + + try { + // Read in two form parameters - the router sets these + operation = (String) input.get(URL_OPERATION); + CMS.debug("operation=" + operation); + message = (String) input.get(URL_MESSAGE); + CMS.debug("message=" + message); + + if (!mEnabled) { + CMS.debug("CRSEnrollment: SCEP support is disabled."); + throw new ServletException("SCEP support is disabled."); + } + if (operation == null) { + // 'operation' is mandatory. + throw new ServletException("Bad request: operation missing from URL"); + } + + /** + * the router can make two kinds of requests + * 1) simple request for CA cert + * 2) encoded, signed, enveloped request for anything else (PKIOperation) + */ + + if (operation.equals(OP_GETCACERT)) { + handleGetCACert(httpReq, httpResp); + } else if (operation.equals(OP_PKIOPERATION)) { + String decodeMode = (String) input.get("decode"); + if (decodeMode == null || decodeMode.equals("false")) { + handlePKIOperation(httpReq, httpResp, message); + } else { + decodePKIMessage(httpReq, httpResp, message); + } + } else { + CMS.debug("Invalid operation " + operation); + throw new ServletException("unknown operation requested: " + operation); + } + + } catch (ServletException e) { + CMS.debug("ServletException " + e); + throw new ServletException(e.getMessage().toString()); + } catch (Exception e) { + CMS.debug("Service exception " + e); + log(ILogger.LL_FAILURE, e.getMessage()); + } + + } + + /** + * Log a message to the system log + */ + + private void log(int level, String msg) { + + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + level, "CEP Enrollment: " + msg); + } + + private boolean isAlgorithmAllowed(String[] allowedAlgorithm, String algorithm) { + boolean allowed = false; + + if (algorithm != null && algorithm.length() > 0) { + for (int i = 0; i < allowedAlgorithm.length; i++) { + if (algorithm.equalsIgnoreCase(allowedAlgorithm[i])) { + allowed = true; + } + } + } + + return allowed; + } + + public IAuthToken authenticate(AuthCredentials credentials, IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + + // build credential + Enumeration<String> 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); + if (authToken == null) { + return null; + } + 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; + } + + /** + * Return the CA certificate back to the requestor. + * This needs to be changed so that if the CA has a certificate chain, + * the whole thing should get packaged as a PKIMessage (degnerate PKCS7 - no + * signerInfo) + */ + + public void handleGetCACert(HttpServletRequest httpReq, + HttpServletResponse httpResp) + throws ServletException { + java.security.cert.X509Certificate[] chain = null; + + CertificateChain certChain = mAuthority.getCACertChain(); + + try { + if (certChain == null) { + throw new ServletException("Internal Error: cannot get CA Cert"); + } + + chain = certChain.getChain(); + + byte[] bytes = null; + + int i = 0; + String message = (String) httpReq.getParameter(URL_MESSAGE); + CMS.debug("handleGetCACert message=" + message); + if (message != null) { + try { + int j = Integer.parseInt(message); + if (j < chain.length) { + i = j; + } + } catch (NumberFormatException e1) { + } + } + CMS.debug("handleGetCACert selected chain=" + i); + + if (mUseCA) { + bytes = chain[i].getEncoded(); + } else { + CryptoContext cx = new CryptoContext(); + bytes = cx.getSigningCert().getEncoded(); + } + + httpResp.setContentType("application/x-x509-ca-cert"); + + // The following code may be used one day to encode + // the RA/CA cert chain for RA mode, but it will need some + // work. + + /****** + * SET certs = new SET(); + * for (int i=0; i<chain.length; i++) { + * ANY cert = new ANY(chain[i].getEncoded()); + * certs.addElement(cert); + * } + * + * SignedData crsd = new SignedData( + * new SET(), // empty set of digestAlgorithmID's + * new ContentInfo( + * new OBJECT_IDENTIFIER(new long[] {1,2,840,113549,1,7,1}), + * null), //empty content + * certs, + * null, // no CRL's + * new SET() // empty SignerInfos + * ); + * + * ContentInfo wrap = new ContentInfo(ContentInfo.SIGNED_DATA, crsd); + * + * ByteArrayOutputStream baos = new ByteArrayOutputStream(); + * wrap.encode(baos); + * + * bytes = baos.toByteArray(); + * + * httpResp.setContentType("application/x-x509-ca-ra-cert"); + *****/ + + httpResp.setContentLength(bytes.length); + httpResp.getOutputStream().write(bytes); + httpResp.getOutputStream().flush(); + + CMS.debug("Output certificate chain:"); + CMS.debug(bytes); + } catch (Exception e) { + CMS.debug("handleGetCACert exception " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_SENDING_DER_ENCODE_CERT", e.getMessage())); + throw new ServletException("Failed sending DER encoded version of CA cert to client"); + } + + } + + public String getPasswordFromP10(PKCS10 p10) { + PKCS10Attributes p10atts = p10.getAttributes(); + Enumeration<PKCS10Attribute> e = p10atts.getElements(); + + try { + while (e.hasMoreElements()) { + PKCS10Attribute p10a = (PKCS10Attribute) e.nextElement(); + CertAttrSet attr = p10a.getAttributeValue(); + + if (attr.getName().equals(ChallengePassword.NAME)) { + if (attr.get(ChallengePassword.PASSWORD) != null) { + return (String) attr.get(ChallengePassword.PASSWORD); + } + } + } + } catch (Exception e1) { + // do nothing + } + return null; + } + + /** + * If the 'operation' is 'PKIOperation', the 'message' part of the URL is a + * PKIMessage structure. We decode it to see what type message it is. + */ + + /** + * Decodes the PKI message and return information to RA. + */ + public void decodePKIMessage(HttpServletRequest httpReq, + HttpServletResponse httpResp, + String msg) + throws ServletException { + + CryptoContext cx = null; + + CRSPKIMessage req = null; + + byte[] decodedPKIMessage; + byte[] response = null; + String responseData = ""; + + decodedPKIMessage = Utils.base64decode(msg); + + try { + ByteArrayInputStream is = new ByteArrayInputStream(decodedPKIMessage); + + // We make two CRSPKIMessages. One of them, is the request, so we initialize + // it from the DER given to us from the router. + // The second is the response, and we'll fill this in as we go. + + if (decodedPKIMessage.length < 50) { + throw new ServletException("CRS request is too small to be a real request (" + + decodedPKIMessage.length + " bytes)"); + } + try { + req = new CRSPKIMessage(is); + String ea = req.getEncryptionAlgorithm(); + if (!isAlgorithmAllowed(mAllowedEncryptionAlgorithm, ea)) { + CMS.debug("CRSEnrollment: decodePKIMessage: Encryption algorithm '" + ea + + "' is not allowed (" + mEncryptionAlgorithmList + ")."); + throw new ServletException("Encryption algorithm '" + ea + + "' is not allowed (" + mEncryptionAlgorithmList + ")."); + } + String da = req.getDigestAlgorithmName(); + if (!isAlgorithmAllowed(mAllowedHashAlgorithm, da)) { + CMS.debug("CRSEnrollment: decodePKIMessage: Hashing algorithm '" + da + + "' is not allowed (" + mHashAlgorithmList + ")."); + throw new ServletException("Hashing algorithm '" + da + + "' is not allowed (" + mHashAlgorithmList + ")."); + } + if (ea != null) { + mEncryptionAlgorithm = ea; + } + } catch (Exception e) { + CMS.debug(e); + throw new ServletException("Could not decode the request."); + } + + // Create a new crypto context for doing all the crypto operations + cx = new CryptoContext(); + + // Verify Signature on message (throws exception if sig bad) + verifyRequest(req, cx); + unwrapPKCS10(req, cx); + + IProfile profile = mProfileSubsystem.getProfile(mProfileId); + if (profile == null) { + CMS.debug("Profile '" + mProfileId + "' not found."); + throw new ServletException("Profile '" + mProfileId + "' not found."); + } else { + CMS.debug("Found profile '" + mProfileId + "'."); + } + + IProfileAuthenticator authenticator = null; + try { + CMS.debug("Retrieving authenticator"); + authenticator = profile.getAuthenticator(); + if (authenticator == null) { + CMS.debug("Authenticator not found."); + throw new ServletException("Authenticator not found."); + } else { + CMS.debug("Got authenticator=" + authenticator.getClass().getName()); + } + } catch (EProfileException e) { + throw new ServletException("Authenticator not found."); + } + AuthCredentials credentials = new AuthCredentials(); + 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("sslClientCertProvider", new SSLClientCertProvider(httpReq)); + + try { + authToken = authenticate(credentials, authenticator, httpReq); + } catch (Exception e) { + CMS.debug("Authentication failure: " + e.getMessage()); + throw new ServletException("Authentication failure: " + e.getMessage()); + } + if (authToken == null) { + CMS.debug("Authentication failure."); + throw new ServletException("Authentication failure."); + } + + // Deal with Transaction ID + String transactionID = req.getTransactionID(); + responseData = responseData + + "<TransactionID>" + transactionID + "</TransactionID>"; + + // End-User or RA's IP address + responseData = responseData + + "<RemoteAddr>" + httpReq.getRemoteAddr() + "</RemoteAddr>"; + + responseData = responseData + + "<RemoteHost>" + httpReq.getRemoteHost() + "</RemoteHost>"; + + // Deal with message type + String mt = req.getMessageType(); + responseData = responseData + + "<MessageType>" + mt + "</MessageType>"; + + PKCS10 p10 = (PKCS10) req.getP10(); + X500Name p10subject = p10.getSubjectName(); + responseData = responseData + + "<SubjectName>" + p10subject.toString() + "</SubjectName>"; + + String pkcs10Attr = ""; + PKCS10Attributes p10atts = p10.getAttributes(); + Enumeration<PKCS10Attribute> e = p10atts.getElements(); + + while (e.hasMoreElements()) { + PKCS10Attribute p10a = (PKCS10Attribute) e.nextElement(); + CertAttrSet attr = p10a.getAttributeValue(); + + if (attr.getName().equals(ChallengePassword.NAME)) { + if (attr.get(ChallengePassword.PASSWORD) != null) { + pkcs10Attr = + pkcs10Attr + + + "<ChallengePassword><Password>" + + (String) attr.get(ChallengePassword.PASSWORD) + + "</Password></ChallengePassword>"; + } + + } + String extensionsStr = ""; + if (attr.getName().equals(ExtensionsRequested.NAME)) { + + Enumeration<Extension> exts = ((ExtensionsRequested) attr).getExtensions().elements(); + while (exts.hasMoreElements()) { + Extension ext = exts.nextElement(); + + if (ext.getExtensionId().equals( + OIDMap.getOID(SubjectAlternativeNameExtension.IDENT))) { + SubjectAlternativeNameExtension sane = new SubjectAlternativeNameExtension( + Boolean.valueOf(false), // noncritical + ext.getExtensionValue()); + + @SuppressWarnings("unchecked") + Vector<GeneralNameInterface> v = + (Vector<GeneralNameInterface>) sane + .get(SubjectAlternativeNameExtension.SUBJECT_NAME); + + Enumeration<GeneralNameInterface> gne = v.elements(); + + StringBuffer subjAltNameStr = new StringBuffer(); + while (gne.hasMoreElements()) { + GeneralNameInterface gni = gne.nextElement(); + if (gni instanceof GeneralName) { + GeneralName genName = (GeneralName) gni; + + String gn = genName.toString(); + int colon = gn.indexOf(':'); + String gnType = gn.substring(0, colon).trim(); + String gnValue = gn.substring(colon + 1).trim(); + + subjAltNameStr.append("<"); + subjAltNameStr.append(gnType); + subjAltNameStr.append(">"); + subjAltNameStr.append(gnValue); + subjAltNameStr.append("</"); + subjAltNameStr.append(gnType); + subjAltNameStr.append(">"); + } + } // while + extensionsStr = "<SubjAltName>" + + subjAltNameStr.toString() + "</SubjAltName>"; + } // if + } // while + pkcs10Attr = pkcs10Attr + + "<Extensions>" + extensionsStr + "</Extensions>"; + } // if extensions + } // while + responseData = responseData + + "<PKCS10>" + pkcs10Attr + "</PKCS10>"; + + } catch (ServletException e) { + throw new ServletException(e.getMessage().toString()); + } catch (CRSInvalidSignatureException e) { + CMS.debug("handlePKIMessage exception " + e); + CMS.debug(e); + } catch (Exception e) { + CMS.debug("handlePKIMessage exception " + e); + CMS.debug(e); + throw new ServletException("Failed to process message in CEP servlet: " + e.getMessage()); + } + + // We have now processed the request, and need to make the response message + + try { + + responseData = "<XMLResponse>" + responseData + "</XMLResponse>"; + // Get the response coding + response = responseData.getBytes(); + + // Encode the httpResp into B64 + httpResp.setContentType("application/xml"); + httpResp.setContentLength(response.length); + httpResp.getOutputStream().write(response); + httpResp.getOutputStream().flush(); + + int i1 = responseData.indexOf("<Password>"); + if (i1 > -1) { + i1 += 10; // 10 is a length of "<Password>" + int i2 = responseData.indexOf("</Password>", i1); + if (i2 > -1) { + responseData = responseData.substring(0, i1) + "********" + + responseData.substring(i2, responseData.length()); + } + } + + CMS.debug("Output (decoding) PKIOperation response:"); + CMS.debug(responseData); + } catch (Exception e) { + throw new ServletException("Failed to create response for CEP message" + e.getMessage()); + } + + } + + /** + * finds a request with this transaction ID. + * If could not find any request - return null + * If could only find 'rejected' or 'cancelled' requests, return null + * If found 'pending' or 'completed' request - return that request + */ + + public void handlePKIOperation(HttpServletRequest httpReq, + HttpServletResponse httpResp, + String msg) + throws ServletException { + + CryptoContext cx = null; + + CRSPKIMessage req = null; + CRSPKIMessage crsResp = null; + + byte[] decodedPKIMessage; + byte[] response = null; + X509CertImpl cert = null; + + decodedPKIMessage = Utils.base64decode(msg); + + try { + ByteArrayInputStream is = new ByteArrayInputStream(decodedPKIMessage); + + // We make two CRSPKIMessages. One of them, is the request, so we initialize + // it from the DER given to us from the router. + // The second is the response, and we'll fill this in as we go. + + if (decodedPKIMessage.length < 50) { + throw new ServletException("CRS request is too small to be a real request (" + + decodedPKIMessage.length + " bytes)"); + } + try { + req = new CRSPKIMessage(is); + String ea = req.getEncryptionAlgorithm(); + if (!isAlgorithmAllowed(mAllowedEncryptionAlgorithm, ea)) { + CMS.debug("CRSEnrollment: handlePKIOperation: Encryption algorithm '" + ea + + "' is not allowed (" + mEncryptionAlgorithmList + ")."); + throw new ServletException("Encryption algorithm '" + ea + + "' is not allowed (" + mEncryptionAlgorithmList + ")."); + } + String da = req.getDigestAlgorithmName(); + if (!isAlgorithmAllowed(mAllowedHashAlgorithm, da)) { + CMS.debug("CRSEnrollment: handlePKIOperation: Hashing algorithm '" + da + + "' is not allowed (" + mHashAlgorithmList + ")."); + throw new ServletException("Hashing algorithm '" + da + + "' is not allowed (" + mHashAlgorithmList + ")."); + } + if (ea != null) { + mEncryptionAlgorithm = ea; + } + crsResp = new CRSPKIMessage(); + } catch (ServletException e) { + throw new ServletException(e.getMessage().toString()); + } catch (Exception e) { + CMS.debug(e); + throw new ServletException("Could not decode the request."); + } + crsResp.setMessageType(CRSPKIMessage.mType_CertRep); + + // Create a new crypto context for doing all the crypto operations + cx = new CryptoContext(); + + // Verify Signature on message (throws exception if sig bad) + verifyRequest(req, cx); + + // Deal with Transaction ID + String transactionID = req.getTransactionID(); + if (transactionID == null) { + throw new ServletException("Error: malformed PKIMessage - missing transactionID"); + } else { + crsResp.setTransactionID(transactionID); + } + + // Deal with Nonces + byte[] sn = req.getSenderNonce(); + if (sn == null) { + throw new ServletException("Error: malformed PKIMessage - missing sendernonce"); + } else { + if (mNonceSizeLimit > 0 && sn.length > mNonceSizeLimit) { + byte[] snLimited = (mNonceSizeLimit > 0) ? new byte[mNonceSizeLimit] : null; + System.arraycopy(sn, 0, snLimited, 0, mNonceSizeLimit); + crsResp.setRecipientNonce(snLimited); + } else { + crsResp.setRecipientNonce(sn); + } + byte[] serverNonce = new byte[16]; + mRandom.nextBytes(serverNonce); + crsResp.setSenderNonce(serverNonce); + // crsResp.setSenderNonce(new byte[] {0}); + } + + // Deal with message type + String mt = req.getMessageType(); + if (mt == null) { + throw new ServletException("Error: malformed PKIMessage - missing messageType"); + } + + // now run appropriate code, depending on message type + if (mt.equals(CRSPKIMessage.mType_PKCSReq)) { + CMS.debug("Processing PKCSReq"); + try { + // Check if there is an existing request. If this returns non-null, + // then the request is 'active' (either pending or completed) in + // which case, we compare the hash of the new request to the hash of the + // one in the queue - if they are the same, I return the state of the + // original request - as if it was 'getCertInitial' message. + // If the hashes are different, then the user attempted to enroll + // for a new request with the same txid, which is not allowed - + // so we return 'failure'. + + IRequest cmsRequest = findRequestByTransactionID(req.getTransactionID(), true); + + // If there was no request (with a cert) with this transaction ID, + // process it as a new request + + cert = handlePKCSReq(httpReq, cmsRequest, req, crsResp, cx); + + } catch (CRSFailureException e) { + throw new ServletException("Couldn't handle CEP request (PKCSReq) - " + e.getMessage()); + } + } else if (mt.equals(CRSPKIMessage.mType_GetCertInitial)) { + CMS.debug("Processing GetCertInitial"); + cert = handleGetCertInitial(req, crsResp); + } else { + CMS.debug("Invalid request type " + mt); + } + } catch (ServletException e) { + throw new ServletException(e.getMessage().toString()); + } catch (CRSInvalidSignatureException e) { + CMS.debug("handlePKIMessage exception " + e); + CMS.debug(e); + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck); + } catch (Exception e) { + CMS.debug("handlePKIMessage exception " + e); + CMS.debug(e); + throw new ServletException("Failed to process message in CEP servlet: " + e.getMessage()); + } + + // We have now processed the request, and need to make the response message + + try { + // make the response + processCertRep(cx, cert, crsResp, req); + + // Get the response coding + response = crsResp.getResponse(); + + // Encode the crsResp into B64 + httpResp.setContentType("application/x-pki-message"); + httpResp.setContentLength(response.length); + httpResp.getOutputStream().write(response); + httpResp.getOutputStream().flush(); + + CMS.debug("Output PKIOperation response:"); + CMS.debug(CMS.BtoA(response)); + } catch (Exception e) { + throw new ServletException("Failed to create response for CEP message" + e.getMessage()); + } + + } + + /** + * finds a request with this transaction ID. + * If could not find any request - return null + * If could only find 'rejected' or 'cancelled' requests, return null + * If found 'pending' or 'completed' request - return that request + */ + + public IRequest findRequestByTransactionID(String txid, boolean ignoreRejected) + throws EBaseException { + + /* Check if certificate request has been completed */ + + IRequestQueue rq = ca.getRequestQueue(); + IRequest foundRequest = null; + + Enumeration<RequestId> rids = rq.findRequestsBySourceId(txid); + if (rids == null) { + return null; + } + + while (rids.hasMoreElements()) { + RequestId rid = rids.nextElement(); + if (rid == null) { + continue; + } + + IRequest request = rq.findRequest(rid); + if (request == null) { + continue; + } + if (!ignoreRejected || + request.getRequestStatus().equals(RequestStatus.PENDING) || + request.getRequestStatus().equals(RequestStatus.COMPLETE)) { + if (foundRequest != null) { + } + foundRequest = request; + } + } + return foundRequest; + } + + /** + * Called if the router is requesting us to send it its certificate + * Examine request queue for a request matching the transaction ID. + * Ignore any rejected or cancelled requests. + * + * If a request is found in the pending state, the response should be + * 'pending' + * + * If a request is found in the completed state, the response should be + * to return the certificate + * + * If no request is found, the response should be to return null + * + */ + + public X509CertImpl handleGetCertInitial(CRSPKIMessage req, CRSPKIMessage resp) { + IRequest foundRequest = null; + + // already done by handlePKIOperation + // resp.setRecipientNonce(req.getSenderNonce()); + // resp.setSenderNonce(null); + + try { + foundRequest = findRequestByTransactionID(req.getTransactionID(), false); + } catch (EBaseException e) { + } + + if (foundRequest == null) { + resp.setFailInfo(CRSPKIMessage.mFailInfo_badCertId); + resp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + return null; + } + + return makeResponseFromRequest(req, resp, foundRequest); + } + + public void verifyRequest(CRSPKIMessage req, CryptoContext cx) + throws CRSInvalidSignatureException { + + // Get Signed Data + + @SuppressWarnings("unused") + byte[] reqAAbytes = req.getAA(); // check for errors + + @SuppressWarnings("unused") + byte[] reqAAsig = req.getAADigest(); // check for errors + + } + + /** + * Create an entry for this user in the publishing directory + * + */ + + private boolean createEntry(String dn) { + boolean result = false; + + IPublisherProcessor ldapPub = mAuthority.getPublisherProcessor(); + if (ldapPub == null || !ldapPub.enabled()) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_CREATE_ENTRY_FROM_CEP")); + + return result; + } + + ILdapConnFactory connFactory = ((IPublisherProcessor) ldapPub).getLdapConnModule().getLdapConnFactory(); + if (connFactory == null) { + return result; + } + + LDAPConnection connection = null; + try { + connection = connFactory.getConn(); + String[] objectclasses = { "top", mEntryObjectclass }; + LDAPAttribute ocAttrs = new LDAPAttribute("objectclass", objectclasses); + + LDAPAttributeSet attrSet = new LDAPAttributeSet(); + attrSet.add(ocAttrs); + + LDAPEntry newEntry = new LDAPEntry(dn, attrSet); + connection.add(newEntry); + result = true; + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_FAIL_CREAT_ENTRY_EXISTS", dn)); + } finally { + try { + connFactory.returnConn(connection); + } catch (Exception f) { + } + } + return result; + } + + /** + * Here we decrypt the PKCS10 message from the client + * + */ + + public void unwrapPKCS10(CRSPKIMessage req, CryptoContext cx) + throws ServletException, + CryptoManager.NotInitializedException, + CryptoContext.CryptoContextException, + CRSFailureException { + + byte[] decryptedP10bytes = null; + SymmetricKey sk; + SymmetricKey skinternal; + SymmetricKey.Type skt; + KeyWrapper kw; + Cipher cip; + EncryptionAlgorithm ea; + + // Unwrap the session key with the Cert server key + try { + kw = cx.getKeyWrapper(); + + kw.initUnwrap(cx.getPrivateKey(), null); + + skt = SymmetricKey.Type.DES; + ea = EncryptionAlgorithm.DES_CBC; + if (mEncryptionAlgorithm != null && mEncryptionAlgorithm.equals("DES3")) { + skt = SymmetricKey.Type.DES3; + ea = EncryptionAlgorithm.DES3_CBC; + } + + sk = kw.unwrapSymmetric(req.getWrappedKey(), + skt, + SymmetricKey.Usage.DECRYPT, + 0); // keylength is ignored + + skinternal = cx.getDESKeyGenerator().clone(sk); + + cip = skinternal.getOwningToken().getCipherContext(ea); + + cip.initDecrypt(skinternal, (new IVParameterSpec(req.getIV()))); + + decryptedP10bytes = cip.doFinal(req.getEncryptedPkcs10()); + CMS.debug("decryptedP10bytes:"); + CMS.debug(decryptedP10bytes); + + req.setP10(new PKCS10(decryptedP10bytes)); + } catch (Exception e) { + CMS.debug("failed to unwrap PKCS10 " + e); + throw new CRSFailureException("Could not unwrap PKCS10 blob: " + e.getMessage()); + } + + } + + private void getDetailFromRequest(CRSPKIMessage req, CRSPKIMessage crsResp) + throws CRSFailureException { + + SubjectAlternativeNameExtension sane = null; + + try { + PKCS10 p10 = req.getP10(); + + if (p10 == null) { + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck); + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + throw new CRSFailureException("Failed to decode pkcs10 from CEP request"); + } + + AuthCredentials authCreds = new AuthCredentials(); + + // Here, we make a new CertInfo - it's a new start for a certificate + + X509CertInfo certInfo = CMS.getDefaultX509CertInfo(); + + // get some stuff out of the request + X509Key key = p10.getSubjectPublicKeyInfo(); + X500Name p10subject = p10.getSubjectName(); + + X500Name subject = null; + + // The following code will copy all the attributes + // into the AuthCredentials so they can be used for + // authentication + // + // Optionally, you can re-map the subject name from: + // one RDN, with many AVA's to + // many RDN's with one AVA in each. + + Enumeration<RDN> rdne = p10subject.getRDNs(); + Vector<RDN> rdnv = new Vector<RDN>(); + + Hashtable<String, String> sanehash = new Hashtable<String, String>(); + + X500NameAttrMap xnap = X500NameAttrMap.getDefault(); + while (rdne.hasMoreElements()) { + RDN rdn = (RDN) rdne.nextElement(); + int i = 0; + AVA[] oldavas = rdn.getAssertion(); + for (i = 0; i < rdn.getAssertionLength(); i++) { + AVA[] newavas = new AVA[1]; + newavas[0] = oldavas[i]; + + authCreds.set(xnap.getName(oldavas[i].getOid()), + oldavas[i].getValue().getAsString()); + + if (oldavas[i].getOid().equals(OID_UNSTRUCTUREDNAME)) { + + sanehash.put(SANE_DNSNAME, oldavas[i].getValue().getAsString()); + } + if (oldavas[i].getOid().equals(OID_UNSTRUCTUREDADDRESS)) { + sanehash.put(SANE_IPADDRESS, oldavas[i].getValue().getAsString()); + } + + RDN newrdn = new RDN(newavas); + if (mFlattenDN) { + rdnv.addElement(newrdn); + } + } + } + + if (mFlattenDN) + subject = new X500Name(rdnv); + else + subject = p10subject; + + // create default key usage extension + KeyUsageExtension kue = new KeyUsageExtension(); + kue.set(KeyUsageExtension.DIGITAL_SIGNATURE, Boolean.valueOf(true)); + kue.set(KeyUsageExtension.KEY_ENCIPHERMENT, Boolean.valueOf(true)); + + PKCS10Attributes p10atts = p10.getAttributes(); + Enumeration<PKCS10Attribute> e = p10atts.getElements(); + + while (e.hasMoreElements()) { + PKCS10Attribute p10a = (PKCS10Attribute) e.nextElement(); + CertAttrSet attr = p10a.getAttributeValue(); + + if (attr.getName().equals(ChallengePassword.NAME)) { + if (attr.get(ChallengePassword.PASSWORD) != null) { + req.put(AUTH_PASSWORD, + (String) attr.get(ChallengePassword.PASSWORD)); + req.put(ChallengePassword.NAME, + hashPassword( + (String) attr.get(ChallengePassword.PASSWORD))); + } + } + + if (attr.getName().equals(ExtensionsRequested.NAME)) { + + Enumeration<Extension> exts = ((ExtensionsRequested) attr).getExtensions().elements(); + while (exts.hasMoreElements()) { + Extension ext = exts.nextElement(); + + if (ext.getExtensionId().equals( + OIDMap.getOID(KeyUsageExtension.IDENT))) { + + kue = new KeyUsageExtension( + new Boolean(false), // noncritical + ext.getExtensionValue()); + } + + if (ext.getExtensionId().equals( + OIDMap.getOID(SubjectAlternativeNameExtension.IDENT))) { + sane = new SubjectAlternativeNameExtension( + new Boolean(false), // noncritical + ext.getExtensionValue()); + + @SuppressWarnings("unchecked") + Vector<GeneralNameInterface> v = + (Vector<GeneralNameInterface>) sane + .get(SubjectAlternativeNameExtension.SUBJECT_NAME); + + Enumeration<GeneralNameInterface> gne = v.elements(); + + while (gne.hasMoreElements()) { + GeneralNameInterface gni = (GeneralNameInterface) gne.nextElement(); + if (gni instanceof GeneralName) { + GeneralName genName = (GeneralName) gni; + + String gn = genName.toString(); + int colon = gn.indexOf(':'); + String gnType = gn.substring(0, colon).trim(); + String gnValue = gn.substring(colon + 1).trim(); + + authCreds.set(gnType, gnValue); + } + } + } + } + } + } + + if (authCreds != null) + req.put(AUTH_CREDS, authCreds); + + try { + if (sane == null) + sane = makeDefaultSubjectAltName(sanehash); + } catch (Exception sane_e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_SUBJ_ALT_NAME", + sane_e.getMessage())); + } + + try { + if (mAppendDN != null && !mAppendDN.equals("")) { + + new X500Name(subject.toString()); // check for errors + + subject = new X500Name(subject.toString().concat("," + mAppendDN)); + } + + } catch (Exception sne) { + log(ILogger.LL_INFO, + "Unable to use appendDN parameter: " + + mAppendDN + ". Error is " + sne.getMessage() + " Using unmodified subjectname"); + } + + if (subject != null) + req.put(SUBJECTNAME, subject); + + if (key == null || subject == null) { + // log + //throw new ERegistrationException(RegistrationResources.ERROR_MALFORMED_P10); + } + + certInfo.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + + certInfo.set(X509CertInfo.SUBJECT, + new CertificateSubjectName(subject)); + + certInfo.set(X509CertInfo.KEY, + new CertificateX509Key(key)); + + CertificateExtensions ext = new CertificateExtensions(); + + if (kue != null) { + ext.set(KeyUsageExtension.NAME, kue); + } + + // add subjectAltName extension, if present + if (sane != null) { + ext.set(SubjectAlternativeNameExtension.NAME, sane); + } + + certInfo.set(X509CertInfo.EXTENSIONS, ext); + + req.put(CERTINFO, certInfo); + } catch (Exception e) { + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck); + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + return; + } // NEED TO FIX + } + + private SubjectAlternativeNameExtension makeDefaultSubjectAltName(Hashtable<String, String> ht) { + + // if no subjectaltname extension was requested, we try to make it up + // from some of the elements of the subject name + + int itemCount = ht.size(); + GeneralNameInterface[] gn = new GeneralNameInterface[ht.size()]; + + itemCount = 0; + Enumeration<String> en = ht.keys(); + while (en.hasMoreElements()) { + String key = (String) en.nextElement(); + if (key.equals(SANE_DNSNAME)) { + gn[itemCount++] = new DNSName((String) ht.get(key)); + } + if (key.equals(SANE_IPADDRESS)) { + gn[itemCount++] = new IPAddressName((String) ht.get(key)); + } + } + + try { + return new SubjectAlternativeNameExtension(new GeneralNames(gn)); + } catch (Exception e) { + log(ILogger.LL_INFO, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_SUBJ_ALT_NAME", + e.getMessage())); + return null; + } + } + + // Perform authentication + + /* + * if the authentication is set up for CEP, and the user provides + * some credential, an attempt is made to authenticate the user + * If this fails, this method will return true + * If it is sucessful, this method will return true and + * an authtoken will be in the request + * + * If authentication is not configured, this method will + * return false. The request will be processed in the usual + * way, but no authtoken will be in the request. + * + * In other word, this method returns true if the request + * should be aborted, false otherwise. + */ + + private boolean authenticateUser(CRSPKIMessage req) { + boolean authenticationFailed = true; + + if (mAuthManagerName == null) { + return false; + } + + String password = (String) req.get(AUTH_PASSWORD); + + AuthCredentials authCreds = (AuthCredentials) req.get(AUTH_CREDS); + + if (authCreds == null) { + authCreds = new AuthCredentials(); + } + + // authtoken starts as null + AuthToken token = null; + + if (password != null && !password.equals("")) { + try { + authCreds.set(AUTH_PASSWORD, password); + } catch (Exception e) { + } + } + + try { + token = (AuthToken) mAuthSubsystem.authenticate(authCreds, mAuthManagerName); + authCreds.delete(AUTH_PASSWORD); + // if we got here, the authenticate call must not have thrown + // an exception + authenticationFailed = false; + } catch (EInvalidCredentials ex) { + // Invalid credentials - we must reject the request + authenticationFailed = true; + } catch (EMissingCredential mc) { + // Misssing credential - we'll log, and process manually + authenticationFailed = false; + } catch (EBaseException ex) { + // If there's some other error, we'll reject + // So, we just continue on, - AUTH_TOKEN will not be set. + } + + if (token != null) { + req.put(AUTH_TOKEN, token); + } + + return authenticationFailed; + } + + private boolean areFingerprintsEqual(IRequest req, Hashtable<String, byte[]> fingerprints) { + + Hashtable<String, String> old_fprints = req.getExtDataInHashtable(IRequest.FINGERPRINTS); + if (old_fprints == null) { + return false; + } + + byte[] old_md5 = CMS.AtoB(old_fprints.get("MD5")); + byte[] new_md5 = fingerprints.get("MD5"); + + if (old_md5.length != new_md5.length) + return false; + + for (int i = 0; i < old_md5.length; i++) { + if (old_md5[i] != new_md5[i]) + return false; + } + return true; + } + + public X509CertImpl handlePKCSReq(HttpServletRequest httpReq, + IRequest cmsRequest, CRSPKIMessage req, + CRSPKIMessage crsResp, CryptoContext cx) + throws ServletException, + CryptoManager.NotInitializedException, + CRSFailureException { + + try { + unwrapPKCS10(req, cx); + Hashtable<String, byte[]> fingerprints = makeFingerPrints(req); + + if (cmsRequest != null) { + if (areFingerprintsEqual(cmsRequest, fingerprints)) { + CMS.debug("created response from request"); + return makeResponseFromRequest(req, crsResp, cmsRequest); + } else { + CMS.debug("duplicated transaction id"); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ENROLL_FAIL_DUP_TRANS_ID")); + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badRequest); + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + return null; + } + } + + getDetailFromRequest(req, crsResp); + boolean authFailed = authenticateUser(req); + + if (authFailed) { + CMS.debug("authentication failed"); + log(ILogger.LL_SECURITY, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_AUTH")); + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badIdentity); + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + + // perform audit log + String auditMessage = CMS.getLogMessage( + "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5", + httpReq.getRemoteAddr(), + ILogger.FAILURE, + req.getTransactionID(), + "CRSEnrollment", + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + ILogger signedAuditLogger = CMS.getSignedAuditLogger(); + if (signedAuditLogger != null) { + signedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, auditMessage); + } + + return null; + } else { + IRequest ireq = postRequest(httpReq, req, crsResp); + + CMS.debug("created response"); + return makeResponseFromRequest(req, crsResp, ireq); + } + } catch (CryptoContext.CryptoContextException e) { + CMS.debug("failed to decrypt the request " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ENROLL_FAIL_NO_DECRYPT_PKCS10", + e.getMessage())); + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badMessageCheck); + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + } catch (EBaseException e) { + CMS.debug("operation failure - " + e); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERNOLL_FAIL_NO_NEW_REQUEST_POSTED", + e.getMessage())); + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_internalCAError); + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + } + return null; + } + + ////// post the request + + /* + needed: + + token (authtoken) + certInfo + fingerprints x + req.transactionID + crsResp + */ + + private IRequest postRequest(HttpServletRequest httpReq, CRSPKIMessage req, CRSPKIMessage crsResp) + throws EBaseException { + X500Name subject = (X500Name) req.get(SUBJECTNAME); + + if (mCreateEntry) { + if (subject == null) { + CMS.debug("CRSEnrollment::postRequest() - subject is null!"); + return null; + } + createEntry(subject.toString()); + } + + // use profile framework to handle SCEP + if (mProfileId != null) { + PKCS10 pkcs10data = req.getP10(); + String pkcs10blob = CMS.BtoA(pkcs10data.toByteArray()); + + // XXX authentication handling + CMS.debug("Found profile=" + mProfileId); + IProfile profile = mProfileSubsystem.getProfile(mProfileId); + if (profile == null) { + CMS.debug("profile " + mProfileId + " not found"); + return null; + } + IProfileContext ctx = profile.createContext(); + + IProfileAuthenticator authenticator = null; + try { + CMS.debug("Retrieving authenticator"); + authenticator = profile.getAuthenticator(); + if (authenticator == null) { + CMS.debug("No authenticator Found"); + } else { + CMS.debug("Got authenticator=" + authenticator.getClass().getName()); + } + } catch (EProfileException e) { + // authenticator not installed correctly + } + + 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(httpReq)); + + String p10Password = getPasswordFromP10(pkcs10data); + AuthCredentials credentials = new AuthCredentials(); + credentials.set("UID", httpReq.getRemoteAddr()); + credentials.set("PWD", p10Password); + + if (authenticator == null) { + // XXX - to help caRouterCert to work, we need to + // add authentication to caRouterCert + authToken = new AuthToken(null); + } else { + authToken = authenticate(credentials, authenticator, httpReq); + } + + IRequest reqs[] = null; + CMS.debug("CRSEnrollment: Creating profile requests"); + ctx.set(IEnrollProfile.CTX_CERT_REQUEST_TYPE, "pkcs10"); + ctx.set(IEnrollProfile.CTX_CERT_REQUEST, pkcs10blob); + Locale locale = Locale.getDefault(); + reqs = profile.createRequests(ctx, locale); + if (reqs == null) { + CMS.debug("CRSEnrollment: No request has been created"); + return null; + } else { + CMS.debug("CRSEnrollment: Request (" + reqs.length + ") have been created"); + } + // set transaction id + reqs[0].setSourceId(req.getTransactionID()); + reqs[0].setExtData("profile", "true"); + reqs[0].setExtData("profileId", mProfileId); + reqs[0].setExtData(IEnrollProfile.CTX_CERT_REQUEST_TYPE, IEnrollProfile.REQ_TYPE_PKCS10); + reqs[0].setExtData(IEnrollProfile.CTX_CERT_REQUEST, pkcs10blob); + reqs[0].setExtData("requestor_name", ""); + reqs[0].setExtData("requestor_email", ""); + reqs[0].setExtData("requestor_phone", ""); + reqs[0].setExtData("profileRemoteHost", httpReq.getRemoteHost()); + reqs[0].setExtData("profileRemoteAddr", httpReq.getRemoteAddr()); + reqs[0].setExtData("profileApprovedBy", profile.getApprovedBy()); + + CMS.debug("CRSEnrollment: Populating inputs"); + profile.populateInput(ctx, reqs[0]); + CMS.debug("CRSEnrollment: Populating requests"); + profile.populate(reqs[0]); + + CMS.debug("CRSEnrollment: Submitting request"); + profile.submit(authToken, reqs[0]); + CMS.debug("CRSEnrollment: Done submitting request"); + profile.getRequestQueue().markAsServiced(reqs[0]); + CMS.debug("CRSEnrollment: Request marked as serviced"); + + return reqs[0]; + + } + + IRequestQueue rq = ca.getRequestQueue(); + IRequest pkiReq = rq.newRequest(IRequest.ENROLLMENT_REQUEST); + + AuthToken token = (AuthToken) req.get(AUTH_TOKEN); + if (token != null) { + pkiReq.setExtData(IRequest.AUTH_TOKEN, token); + } + + pkiReq.setExtData(IRequest.HTTP_PARAMS, IRequest.CERT_TYPE, IRequest.CEP_CERT); + X509CertInfo certInfo = (X509CertInfo) req.get(CERTINFO); + pkiReq.setExtData(IRequest.CERT_INFO, new X509CertInfo[] { certInfo }); + pkiReq.setExtData("cepsubstore", mSubstoreName); + + try { + String chpwd = (String) req.get(ChallengePassword.NAME); + if (chpwd != null) { + pkiReq.setExtData("challengePhrase", + chpwd); + } + } catch (Exception pwex) { + } + + Hashtable<?, ?> fingerprints = (Hashtable<?, ?>) req.get(IRequest.FINGERPRINTS); + if (fingerprints.size() > 0) { + Hashtable<String, String> encodedPrints = new Hashtable<String, String>(fingerprints.size()); + Enumeration<?> e = fingerprints.keys(); + while (e.hasMoreElements()) { + String key = (String) e.nextElement(); + byte[] value = (byte[]) fingerprints.get(key); + encodedPrints.put(key, CMS.BtoA(value)); + } + pkiReq.setExtData(IRequest.FINGERPRINTS, encodedPrints); + } + + pkiReq.setSourceId(req.getTransactionID()); + + rq.processRequest(pkiReq); + + crsResp.setPKIStatus(CRSPKIMessage.mStatus_SUCCESS); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.ENROLLMENTFORMAT, + new Object[] { + pkiReq.getRequestId(), + AuditFormat.FROMROUTER, + mAuthManagerName == null ? AuditFormat.NOAUTH : mAuthManagerName, + "pending", + subject, + "" } + ); + + return pkiReq; + } + + public Hashtable<String, byte[]> makeFingerPrints(CRSPKIMessage req) { + Hashtable<String, byte[]> fingerprints = new Hashtable<String, byte[]>(); + + MessageDigest md; + String[] hashes = new String[] { "MD2", "MD5", "SHA1", "SHA256", "SHA512" }; + PKCS10 p10 = (PKCS10) req.getP10(); + + for (int i = 0; i < hashes.length; i++) { + try { + md = MessageDigest.getInstance(hashes[i]); + md.update(p10.getCertRequestInfo()); + fingerprints.put(hashes[i], md.digest()); + } catch (NoSuchAlgorithmException nsa) { + } + } + + if (fingerprints != null) { + req.put(IRequest.FINGERPRINTS, fingerprints); + } + return fingerprints; + } + + // Take a look to see if the request was successful, and fill + // in the response message + + private X509CertImpl makeResponseFromRequest(CRSPKIMessage crsReq, CRSPKIMessage crsResp, + IRequest pkiReq) { + + X509CertImpl issuedCert = null; + + RequestStatus status = pkiReq.getRequestStatus(); + + String profileId = pkiReq.getExtDataInString("profileId"); + if (profileId != null) { + CMS.debug("CRSEnrollment: Found profile request"); + X509CertImpl cert = + pkiReq.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); + if (cert == null) { + CMS.debug("CRSEnrollment: No certificate has been found"); + } else { + CMS.debug("CRSEnrollment: Found certificate"); + } + crsResp.setPKIStatus(CRSPKIMessage.mStatus_SUCCESS); + return cert; + } + + if (status.equals(RequestStatus.COMPLETE)) { + Integer success = pkiReq.getExtDataInInteger(IRequest.RESULT); + + if (success.equals(IRequest.RES_SUCCESS)) { + // The cert was issued, lets send it back to the router + X509CertImpl[] issuedCertBuf = + pkiReq.getExtDataInCertArray(IRequest.ISSUED_CERTS); + if (issuedCertBuf == null || issuedCertBuf.length == 0) { + // writeError("Internal Error: Bad operation",httpReq,httpResp); + CMS.debug("CRSEnrollment::makeResponseFromRequest() - " + + "Bad operation"); + return null; + } + issuedCert = issuedCertBuf[0]; + crsResp.setPKIStatus(CRSPKIMessage.mStatus_SUCCESS); + + } else { // status is not 'success' - there must've been a problem + + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badAlg); + } + } else if (status.equals(RequestStatus.REJECTED_STRING) || + status.equals(RequestStatus.CANCELED_STRING)) { + crsResp.setPKIStatus(CRSPKIMessage.mStatus_FAILURE); + crsResp.setFailInfo(CRSPKIMessage.mFailInfo_badRequest); + } else { // not complete + crsResp.setPKIStatus(CRSPKIMessage.mStatus_PENDING); + } + + return issuedCert; + } + + protected String hashPassword(String pwd) { + String salt = "lala123"; + byte[] pwdDigest = mSHADigest.digest((salt + pwd).getBytes()); + String b64E = Utils.base64encode(pwdDigest); + return "{SHA}" + b64E; + } + + /** + * Make the CRSPKIMESSAGE response + */ + + private void processCertRep(CryptoContext cx, + X509CertImpl issuedCert, + CRSPKIMessage crsResp, + CRSPKIMessage crsReq) + throws CRSFailureException { + byte[] msgdigest = null; + byte[] encryptedDesKey = null; + + try { + if (issuedCert != null) { + + SymmetricKey sk; + SymmetricKey skinternal; + + KeyGenAlgorithm kga = KeyGenAlgorithm.DES; + EncryptionAlgorithm ea = EncryptionAlgorithm.DES_CBC; + if (mEncryptionAlgorithm != null && mEncryptionAlgorithm.equals("DES3")) { + kga = KeyGenAlgorithm.DES3; + ea = EncryptionAlgorithm.DES3_CBC; + } + + // 1. Make the Degenerated PKCS7 with the recipient's certificate in it + + byte toBeEncrypted[] = + crsResp.makeSignedRep(1, // version + issuedCert.getEncoded() + ); + + // 2. Encrypt the above byte array with a new random DES key + + sk = cx.getDESKeyGenerator().generate(); + + skinternal = cx.getInternalToken().getKeyGenerator(kga).clone(sk); + + byte[] padded = Cipher.pad(toBeEncrypted, ea.getBlockSize()); + + // This should be changed to generate proper DES IV. + + Cipher cipher = cx.getInternalToken().getCipherContext(ea); + IVParameterSpec desIV = + new IVParameterSpec(new byte[] { + (byte) 0xff, (byte) 0x00, + (byte) 0xff, (byte) 0x00, + (byte) 0xff, (byte) 0x00, + (byte) 0xff, (byte) 0x00 }); + + cipher.initEncrypt(sk, desIV); + byte[] encryptedData = cipher.doFinal(padded); + + crsResp.makeEncryptedContentInfo(desIV.getIV(), encryptedData, mEncryptionAlgorithm); + + // 3. Extract the recipient's public key + + PublicKey rcpPK = crsReq.getSignerPublicKey(); + + // 4. Encrypt the DES key with the public key + + // we have to move the key onto the interal token. + //skinternal = cx.getInternalKeyStorageToken().cloneKey(sk); + skinternal = cx.getInternalToken().cloneKey(sk); + + KeyWrapper kw = cx.getInternalKeyWrapper(); + kw.initWrap(rcpPK, null); + encryptedDesKey = kw.wrap(skinternal); + + crsResp.setRcpIssuerAndSerialNumber(crsReq.getSgnIssuerAndSerialNumber()); + crsResp.makeRecipientInfo(0, encryptedDesKey); + + } + + byte[] ed = crsResp.makeEnvelopedData(0); + + // 7. Make Digest of SignedData Content + MessageDigest md = MessageDigest.getInstance(mHashAlgorithm); + msgdigest = md.digest(ed); + + crsResp.setMsgDigest(msgdigest); + + } + + catch (Exception e) { + throw new CRSFailureException("Failed to create inner response to CEP message: " + e.getMessage()); + } + + // 5. Make a RecipientInfo + + // The issuer name & serial number here, should be that of + // the EE's self-signed Certificate + // [I can get it from the req blob, but later, I should + // store the recipient's self-signed certificate with the request + // so I can get at it later. I need to do this to support + // 'PENDING'] + + try { + + // 8. Make Authenticated Attributes + // we can just pull the transaction ID out of the request. + // Later, we will have to put it out of the Request queue, + // so we can support PENDING + crsResp.setTransactionID(crsReq.getTransactionID()); + // recipientNonce and SenderNonce have already been set + + crsResp.makeAuthenticatedAttributes(); + // crsResp.makeAuthenticatedAttributes_old(); + + // now package up the rest of the SignerInfo + { + byte[] signingcertbytes = cx.getSigningCert().getEncoded(); + + Certificate.Template sgncert_t = new Certificate.Template(); + Certificate sgncert = + (Certificate) sgncert_t.decode(new ByteArrayInputStream(signingcertbytes)); + + IssuerAndSerialNumber sgniasn = + new IssuerAndSerialNumber(sgncert.getInfo().getIssuer(), + sgncert.getInfo().getSerialNumber()); + + crsResp.setSgnIssuerAndSerialNumber(sgniasn); + + // 10. Make SignerInfo + crsResp.makeSignerInfo(1, cx.getPrivateKey(), mHashAlgorithm); + + // 11. Make SignedData + crsResp.makeSignedData(1, signingcertbytes, mHashAlgorithm); + + crsResp.debug(); + } + } catch (Exception e) { + throw new CRSFailureException("Failed to create outer response to CEP request: " + e.getMessage()); + } + + // if debugging, dump out the response into a file + + } + + class CryptoContext { + private CryptoManager cm; + private CryptoToken internalToken; + private CryptoToken keyStorageToken; + private CryptoToken internalKeyStorageToken; + private KeyGenerator DESkg; + private Enumeration<?> externalTokens = null; + private org.mozilla.jss.crypto.X509Certificate signingCert; + private org.mozilla.jss.crypto.PrivateKey signingCertPrivKey; + private int signingCertKeySize = 0; + + class CryptoContextException extends Exception { + /** + * + */ + private static final long serialVersionUID = -1124116326126256475L; + + public CryptoContextException() { + super(); + } + + public CryptoContextException(String s) { + super(s); + } + } + + public CryptoContext() + throws CryptoContextException { + try { + KeyGenAlgorithm kga = KeyGenAlgorithm.DES; + if (mEncryptionAlgorithm != null && mEncryptionAlgorithm.equals("DES3")) { + kga = KeyGenAlgorithm.DES3; + } + cm = CryptoManager.getInstance(); + internalToken = cm.getInternalCryptoToken(); + DESkg = internalToken.getKeyGenerator(kga); + if (mTokenName.equalsIgnoreCase(Constants.PR_INTERNAL_TOKEN) || + mTokenName.equalsIgnoreCase("Internal Key Storage Token") || + mTokenName.length() == 0) { + keyStorageToken = cm.getInternalKeyStorageToken(); + internalKeyStorageToken = keyStorageToken; + CMS.debug("CRSEnrollment: CryptoContext: internal token name: '" + mTokenName + "'"); + } else { + keyStorageToken = cm.getTokenByName(mTokenName); + internalKeyStorageToken = null; + } + if (!mUseCA && internalKeyStorageToken == null) { + PasswordCallback cb = CMS.getPasswordCallback(); + keyStorageToken.login(cb); // ONE_TIME by default. + } + signingCert = cm.findCertByNickname(mNickname); + signingCertPrivKey = cm.findPrivKeyByCert(signingCert); + byte[] encPubKeyInfo = signingCert.getPublicKey().getEncoded(); + SEQUENCE.Template outer = SEQUENCE.getTemplate(); + outer.addElement(ANY.getTemplate()); // algid + outer.addElement(BIT_STRING.getTemplate()); + SEQUENCE outerSeq = (SEQUENCE) ASN1Util.decode(outer, encPubKeyInfo); + BIT_STRING bs = (BIT_STRING) outerSeq.elementAt(1); + byte[] encPubKey = bs.getBits(); + if (bs.getPadCount() != 0) { + throw new CryptoContextException( + "Internal error: Invalid Public key. Not an integral number of bytes."); + } + SEQUENCE.Template inner = new SEQUENCE.Template(); + inner.addElement(INTEGER.getTemplate()); + inner.addElement(INTEGER.getTemplate()); + SEQUENCE pubKeySeq = (SEQUENCE) ASN1Util.decode(inner, encPubKey); + INTEGER modulus = (INTEGER) pubKeySeq.elementAt(0); + signingCertKeySize = modulus.bitLength(); + + try { + FileOutputStream fos = new FileOutputStream("pubkey.der"); + fos.write(signingCert.getPublicKey().getEncoded()); + fos.close(); + } catch (Exception e) { + } + + } catch (InvalidBERException e) { + throw new CryptoContextException( + "Internal Error: Bad internal Certificate Representation. Not a valid RSA-signed certificate"); + } catch (CryptoManager.NotInitializedException e) { + throw new CryptoContextException("Crypto Manager not initialized"); + } catch (NoSuchAlgorithmException e) { + throw new CryptoContextException("Cannot create DES key generator"); + } catch (ObjectNotFoundException e) { + throw new CryptoContextException("Certificate not found: " + ca.getNickname()); + } catch (TokenException e) { + throw new CryptoContextException("Problem with Crypto Token: " + e.getMessage()); + } catch (NoSuchTokenException e) { + throw new CryptoContextException("Crypto Token not found: " + e.getMessage()); + } catch (IncorrectPasswordException e) { + throw new CryptoContextException("Incorrect Password."); + } + } + + public KeyGenerator getDESKeyGenerator() { + return DESkg; + } + + public CryptoToken getInternalToken() { + return internalToken; + } + + public void setExternalTokens(Enumeration<?> tokens) { + externalTokens = tokens; + } + + public Enumeration<?> getExternalTokens() { + return externalTokens; + } + + public CryptoToken getInternalKeyStorageToken() { + return internalKeyStorageToken; + } + + public CryptoToken getKeyStorageToken() { + return keyStorageToken; + } + + public CryptoManager getCryptoManager() { + return cm; + } + + public KeyWrapper getKeyWrapper() + throws CryptoContextException { + try { + return signingCertPrivKey.getOwningToken().getKeyWrapper(KeyWrapAlgorithm.RSA); + } catch (TokenException e) { + throw new CryptoContextException("Problem with Crypto Token: " + e.getMessage()); + } catch (NoSuchAlgorithmException e) { + throw new CryptoContextException(e.getMessage()); + } + } + + public KeyWrapper getInternalKeyWrapper() + throws CryptoContextException { + try { + return getInternalToken().getKeyWrapper(KeyWrapAlgorithm.RSA); + } catch (TokenException e) { + throw new CryptoContextException("Problem with Crypto Token: " + e.getMessage()); + } catch (NoSuchAlgorithmException e) { + throw new CryptoContextException(e.getMessage()); + } + } + + public org.mozilla.jss.crypto.PrivateKey getPrivateKey() { + return signingCertPrivKey; + } + + public org.mozilla.jss.crypto.X509Certificate getSigningCert() { + return signingCert; + } + + } + + /* General failure. The request/response cannot be processed. */ + + class CRSFailureException extends Exception { + /** + * + */ + private static final long serialVersionUID = 1962741611501549051L; + + public CRSFailureException() { + super(); + } + + public CRSFailureException(String s) { + super(s); + } + } + + class CRSInvalidSignatureException extends Exception { + /** + * + */ + private static final long serialVersionUID = 9096408193567657944L; + + public CRSInvalidSignatureException() { + super(); + } + + public CRSInvalidSignatureException(String s) { + super(s); + } + } + + class CRSPolicyException extends Exception { + /** + * + */ + private static final long serialVersionUID = 5846593800658787396L; + + public CRSPolicyException() { + super(); + } + + public CRSPolicyException(String s) { + super(s); + } + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java b/base/common/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java new file mode 100644 index 000000000..ff55dc9ce --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java @@ -0,0 +1,141 @@ +// --- 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.cert.scep; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.cert.CertificateException; +import java.util.Enumeration; +import java.util.Vector; + +import netscape.security.util.DerValue; +import netscape.security.x509.CertAttrSet; + +/** + * Class for handling the decoding of a SCEP Challenge Password + * object. Currently this class cannot be used for encoding + * thus some fo the methods are unimplemented + */ +public class ChallengePassword implements CertAttrSet { + + public static final String NAME = "ChallengePassword"; + public static final String PASSWORD = "password"; + + private String cpw; + + /** + * Get the password marshalled in this object + * + * @return the challenge password + */ + public String toString() { + return cpw; + } + + /** + * Create a ChallengePassword object + * + * @param stuff (must be of type byte[]) a DER-encoded by array following + * The ASN.1 template for ChallenegePassword specified in the SCEP + * documentation + * @throws IOException if the DER encoded byt array was malformed, or if it + * did not match the template + */ + + public ChallengePassword(Object stuff) + throws IOException { + + ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff); + try { + decode(is); + } catch (Exception e) { + throw new IOException(e.getMessage()); + } + + } + + /** + * Currently Unimplemented + */ + public void encode(OutputStream out) + throws CertificateException, IOException { + } + + public void decode(InputStream in) + throws CertificateException, IOException { + DerValue derVal = new DerValue(in); + + construct(derVal); + + } + + private void construct(DerValue derVal) throws IOException { + try { + cpw = derVal.getPrintableString(); + } catch (NullPointerException e) { + cpw = ""; + } + } + + /** + * Currently Unimplemented + */ + public void set(String name, Object obj) + throws CertificateException, IOException { + } + + /** + * Get an attribute of this object. + * + * @param name the name of the attribute of this object to get. The only + * supported attribute is "password" + */ + public Object get(String name) + throws CertificateException, IOException { + if (name.equalsIgnoreCase(PASSWORD)) { + return cpw; + } else { + throw new IOException("Attribute name not recognized by " + + "CertAttrSet: ChallengePassword"); + } + } + + /** + * Currently Unimplemented + */ + public void delete(String name) + throws CertificateException, IOException { + } + + /** + * @return an empty set of elements + */ + public Enumeration<String> getAttributeNames() { + return (new Vector<String>()).elements(); + } + + /** + * @return the String "ChallengePassword" + */ + public String getName() { + return NAME; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java b/base/common/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java new file mode 100644 index 000000000..85f3938b8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java @@ -0,0 +1,176 @@ +// --- 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.cert.scep; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.cert.CertificateException; +import java.util.Enumeration; +import java.util.Vector; + +import netscape.security.util.DerInputStream; +import netscape.security.util.DerValue; +import netscape.security.x509.CertAttrSet; +import netscape.security.x509.Extension; + +public class ExtensionsRequested implements CertAttrSet { + + public static final String NAME = "EXTENSIONS_REQUESTED"; + + public static final String KUE_DIGITAL_SIGNATURE = "kue_digital_signature"; + public static final String KUE_KEY_ENCIPHERMENT = "kue_key_encipherment"; + + private String kue_digital_signature = "false"; + private String kue_key_encipherment = "false"; + + private Vector<Extension> exts = new Vector<Extension>(); + + public ExtensionsRequested(Object stuff) throws IOException { + ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff); + + try { + decode(is); + } catch (Exception e) { + e.printStackTrace(); + throw new IOException(e.getMessage()); + } + } + + public void encode(OutputStream out) + throws CertificateException, IOException { + } + + public void decode(InputStream in) + throws CertificateException, IOException { + DerValue derVal = new DerValue(in); + + construct(derVal); + } + + public void set(String name, Object obj) + throws CertificateException, IOException { + } + + public Object get(String name) + throws CertificateException, IOException { + if (name.equalsIgnoreCase(KUE_DIGITAL_SIGNATURE)) { + return kue_digital_signature; + } + if (name.equalsIgnoreCase(KUE_KEY_ENCIPHERMENT)) { + return kue_key_encipherment; + } + + throw new IOException("Unsupported attribute queried"); + } + + public void delete(String name) + throws CertificateException, IOException { + } + + public Enumeration<String> getAttributeNames() { + return (new Vector<String>()).elements(); + } + + public String getName() { + return NAME; + } + + /** + * construct - expects this in the inputstream (from the router): + * + * 211 30 31: SEQUENCE { + * 213 06 10: OBJECT IDENTIFIER '2 16 840 1 113733 1 9 8' + * 225 31 17: SET { + * 227 04 15: OCTET STRING, encapsulates { + * 229 30 13: SEQUENCE { + * 231 30 11: SEQUENCE { + * 233 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15) + * 238 04 4: OCTET STRING + * : 03 02 05 A0 + * : } + * : } + * : } + * + * or this (from IRE client): + * + * 262 30 51: SEQUENCE { + * 264 06 9: OBJECT IDENTIFIER extensionReq (1 2 840 113549 1 9 14) + * 275 31 38: SET { + * 277 30 36: SEQUENCE { + * 279 30 34: SEQUENCE { + * 281 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17) + * 286 04 27: OCTET STRING + * : 30 19 87 04 D0 0C 3E 6F 81 03 61 61 61 82 0C 61 + * : 61 61 2E 6D 63 6F 6D 2E 63 6F 6D + * : } + * : } + * : } + * : } + */ + private void construct(DerValue dv) throws IOException { + + DerInputStream stream = null; + + try { // try decoding as sequence first + + stream = dv.toDerInputStream(); + + stream.getDerValue(); // consume stream + stream.reset(); + + stream.getSequence(2); // consume stream + } catch (IOException ioe) { + // if it failed, the outer sequence may be + // encapsulated in an octet string, as in the first + // example above + + byte[] octet_string = dv.getOctetString(); + + // Make a new input stream from the byte array, + // and re-parse it as a sequence. + + dv = new DerValue(octet_string); + + stream = dv.toDerInputStream(); + stream.getSequence(2); // consume stream + } + + // now, the stream will be in the correct format + stream.reset(); + + while (true) { + DerValue ext_dv = null; + try { + ext_dv = stream.getDerValue(); + } catch (IOException ex) { + break; + } + + Extension ext = new Extension(ext_dv); + exts.addElement(ext); + } + + } + + public Vector<Extension> getExtensions() { + return exts; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java b/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java new file mode 100644 index 000000000..88369ace3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java @@ -0,0 +1,109 @@ +// --- 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.common; + +import java.util.Enumeration; +import java.util.Hashtable; + +import com.netscape.certsrv.authentication.IAuthCredentials; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; + +/** + * Authentication Credentials as input to the authMgr + * <P> + * + * @version $Revision$, $Date$ + */ +public class AuthCredentials implements IAuthCredentials { + /** + * + */ + private static final long serialVersionUID = -5995164231849154265L; + private Hashtable<String, Object> authCreds = null; + // Inserted by bskim + private IArgBlock argblk = null; + + // Insert end + + public AuthCredentials() { + authCreds = new Hashtable<String, Object>(); + } + + /** + * sets a credential with credential name and the credential + * + * @param name credential name + * @param cred credential + * @exception com.netscape.certsrv.base.EBaseException NullPointerException + */ + public void set(String name, Object cred) throws EBaseException { + if (cred == null) { + throw new EBaseException("AuthCredentials.set()"); + } + + authCreds.put(name, cred); + } + + /** + * returns the credential to which the specified name is mapped in this + * credential set + * + * @param name credential name + * @return the named authentication credential + */ + public Object get(String name) { + return authCreds.get(name); + } + + /** + * removes the name and its corresponding credential from this + * credential set. This method does nothing if the named + * credential is not in the credential set. + * + * @param name credential name + */ + public void delete(String name) { + authCreds.remove(name); + } + + /** + * returns an enumeration of the credential names in this credential + * set. Use the Enumeration methods on the returned object to + * fetch the elements sequentially. + * + * @return an enumeration of the names in this credential set + * @see java.util.Enumeration + */ + public Enumeration<String> getElements() { + return authCreds.keys(); + } + + // Inserted by bskim + public void setArgBlock(IArgBlock blk) { + argblk = blk; + return; + } + + // Insert end + + public IArgBlock getArgBlock() { + return argblk; + } + // Insert end +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/base/common/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java new file mode 100644 index 000000000..38fcf24f9 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java @@ -0,0 +1,1112 @@ +// --- 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.common; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.util.Date; +import java.util.Hashtable; + +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.InvalidityDateExtension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.ENUMERATED; +import org.mozilla.jss.asn1.GeneralizedTime; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.asn1.UTF8String; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.pkcs11.PK11PubKey; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cmc.CMCCertId; +import org.mozilla.jss.pkix.cmc.CMCStatusInfo; +import org.mozilla.jss.pkix.cmc.GetCert; +import org.mozilla.jss.pkix.cmc.OtherInfo; +import org.mozilla.jss.pkix.cmc.OtherMsg; +import org.mozilla.jss.pkix.cmc.PendInfo; +import org.mozilla.jss.pkix.cmc.ResponseBody; +import org.mozilla.jss.pkix.cmc.TaggedAttribute; +import org.mozilla.jss.pkix.cmmf.RevRequest; +import org.mozilla.jss.pkix.cms.ContentInfo; +import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo; +import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber; +import org.mozilla.jss.pkix.cms.SignedData; +import org.mozilla.jss.pkix.cms.SignerIdentifier; +import org.mozilla.jss.pkix.cms.SignerInfo; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.Name; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.ISharedToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; + +/** + * Utility CMCOutputTemplate + * + * @version $ $, $Date$ + */ +public class CMCOutputTemplate { + public CMCOutputTemplate() { + } + + public void createFullResponseWithFailedStatus(HttpServletResponse resp, + SEQUENCE bpids, int code, UTF8String s) { + SEQUENCE controlSeq = new SEQUENCE(); + SEQUENCE cmsSeq = new SEQUENCE(); + SEQUENCE otherMsgSeq = new SEQUENCE(); + + int bpid = 1; + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(code), null); + CMCStatusInfo cmcStatusInfo = new CMCStatusInfo( + new INTEGER(CMCStatusInfo.FAILED), + bpids, s, otherInfo); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + + try { + ResponseBody respBody = new ResponseBody(controlSeq, + cmsSeq, otherMsgSeq); + + SET certs = new SET(); + ContentInfo contentInfo = getContentInfo(respBody, certs); + if (contentInfo == null) + return; + ByteArrayOutputStream fos = new ByteArrayOutputStream(); + contentInfo.encode(fos); + fos.close(); + byte[] contentBytes = fos.toByteArray(); + + resp.setContentType("application/pkcs7-mime"); + resp.setContentLength(contentBytes.length); + OutputStream os = resp.getOutputStream(); + os.write(contentBytes); + os.flush(); + } catch (Exception e) { + CMS.debug("CMCOutputTemplate createFullResponseWithFailedStatus Exception: " + e.toString()); + return; + } + } + + public void createFullResponse(HttpServletResponse resp, IRequest[] reqs, + String cert_request_type, int[] error_codes) { + + SEQUENCE controlSeq = new SEQUENCE(); + SEQUENCE cmsSeq = new SEQUENCE(); + SEQUENCE otherMsgSeq = new SEQUENCE(); + SessionContext context = SessionContext.getContext(); + + // set status info control for simple enrollment request + // in rfc 2797: body list value is 1 + int bpid = 1; + SEQUENCE pending_bpids = null; + SEQUENCE success_bpids = null; + SEQUENCE failed_bpids = null; + if (cert_request_type.equals("crmf") || + cert_request_type.equals("pkcs10")) { + String reqId = reqs[0].getRequestId().toString(); + OtherInfo otherInfo = null; + if (error_codes[0] == 2) { + PendInfo pendInfo = new PendInfo(reqId, new Date()); + otherInfo = new OtherInfo(OtherInfo.PEND, null, + pendInfo); + } else { + otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_REQUEST), null); + } + + SEQUENCE bpids = new SEQUENCE(); + bpids.addElement(new INTEGER(1)); + CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, + bpids, (String) null, otherInfo); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } else if (cert_request_type.equals("cmc")) { + pending_bpids = new SEQUENCE(); + success_bpids = new SEQUENCE(); + failed_bpids = new SEQUENCE(); + if (reqs != null) { + for (int i = 0; i < reqs.length; i++) { + if (error_codes[i] == 0) { + success_bpids.addElement(new INTEGER( + reqs[i].getExtDataInBigInteger("bodyPartId"))); + } else if (error_codes[i] == 2) { + pending_bpids.addElement(new INTEGER( + reqs[i].getExtDataInBigInteger("bodyPartId"))); + } else { + failed_bpids.addElement(new INTEGER( + reqs[i].getExtDataInBigInteger("bodyPartId"))); + } + } + } + + TaggedAttribute tagattr = null; + CMCStatusInfo cmcStatusInfo = null; + SEQUENCE identityBpids = (SEQUENCE) context.get("identityProof"); + if (identityBpids != null && identityBpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_IDENTITY), null); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, + identityBpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + + SEQUENCE POPLinkWitnessBpids = (SEQUENCE) context.get("POPLinkWitness"); + if (POPLinkWitnessBpids != null && POPLinkWitnessBpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_REQUEST), null); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, + POPLinkWitnessBpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + + if (pending_bpids.size() > 0) { + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, + pending_bpids, (String) null, null); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + + if (success_bpids.size() > 0) { + boolean confirmRequired = false; + try { + confirmRequired = + CMS.getConfigStore().getBoolean("cmc.cert.confirmRequired", + false); + } catch (Exception e) { + } + if (confirmRequired) { + CMS.debug("CMCOutputTemplate: confirmRequired in the request"); + cmcStatusInfo = + new CMCStatusInfo(CMCStatusInfo.CONFIRM_REQUIRED, + success_bpids, (String) null, null); + } else { + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, + success_bpids, (String) null, null); + } + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + + if (failed_bpids.size() > 0) { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_REQUEST), null); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, + failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + } + + SET certs = new SET(); + + try { + // deal with controls + Integer nums = (Integer) (context.get("numOfControls")); + if (nums != null && nums.intValue() > 0) { + TaggedAttribute attr = + (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_getCert)); + if (attr != null) { + try { + processGetCertControl(attr, certs); + } catch (EBaseException ee) { + CMS.debug("CMCOutputTemplate: " + ee.toString()); + OtherInfo otherInfo1 = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_CERT_ID), null); + SEQUENCE bpids1 = new SEQUENCE(); + bpids1.addElement(attr.getBodyPartID()); + CMCStatusInfo cmcStatusInfo1 = new CMCStatusInfo( + new INTEGER(CMCStatusInfo.FAILED), + bpids1, null, otherInfo1); + TaggedAttribute tagattr1 = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo1); + controlSeq.addElement(tagattr1); + } + } + + attr = + (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_dataReturn)); + if (attr != null) + bpid = processDataReturnControl(attr, controlSeq, bpid); + + attr = + (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_transactionId); + if (attr != null) + bpid = processTransactionControl(attr, controlSeq, bpid); + + attr = + (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_senderNonce); + if (attr != null) + bpid = processSenderNonceControl(attr, controlSeq, bpid); + + attr = + (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_QueryPending); + if (attr != null) + bpid = processQueryPendingControl(attr, controlSeq, bpid); + + attr = + (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_idConfirmCertAcceptance); + + if (attr != null) + bpid = processConfirmCertAcceptanceControl(attr, controlSeq, + bpid); + + attr = + (TaggedAttribute) context.get(OBJECT_IDENTIFIER.id_cmc_revokeRequest); + + if (attr != null) + bpid = processRevokeRequestControl(attr, controlSeq, + bpid); + } + + if (success_bpids != null && success_bpids.size() > 0) { + for (int i = 0; i < reqs.length; i++) { + if (error_codes[i] == 0) { + X509CertImpl impl = + (reqs[i].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT)); + byte[] bin = impl.getEncoded(); + Certificate.Template certTemplate = new Certificate.Template(); + Certificate cert = (Certificate) certTemplate.decode( + new ByteArrayInputStream(bin)); + certs.addElement(cert); + } + } + } + + ResponseBody respBody = new ResponseBody(controlSeq, + cmsSeq, otherMsgSeq); + + ContentInfo contentInfo = getContentInfo(respBody, certs); + ByteArrayOutputStream fos = new ByteArrayOutputStream(); + contentInfo.encode(fos); + fos.close(); + byte[] contentBytes = fos.toByteArray(); + + resp.setContentType("application/pkcs7-mime"); + resp.setContentLength(contentBytes.length); + OutputStream os = resp.getOutputStream(); + os.write(contentBytes); + os.flush(); + } catch (java.security.cert.CertificateEncodingException e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); + } catch (InvalidBERException e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); + } catch (IOException e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); + } catch (Exception e) { + CMS.debug("Exception: " + e.toString()); + } + } + + private ContentInfo getContentInfo(ResponseBody respBody, SET certs) { + try { + ICertificateAuthority ca = null; + // add CA cert chain + ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + CertificateChain certchains = ca.getCACertChain(); + java.security.cert.X509Certificate[] chains = certchains.getChain(); + + for (int i = 0; i < chains.length; i++) { + Certificate.Template certTemplate = new Certificate.Template(); + Certificate cert = (Certificate) certTemplate.decode( + new ByteArrayInputStream(chains[i].getEncoded())); + certs.addElement(cert); + } + + EncapsulatedContentInfo enContentInfo = new EncapsulatedContentInfo( + OBJECT_IDENTIFIER.id_cct_PKIResponse, respBody); + org.mozilla.jss.crypto.X509Certificate x509CAcert = null; + x509CAcert = ca.getCaX509Cert(); + X509CertImpl caimpl = new X509CertImpl(x509CAcert.getEncoded()); + X500Name issuerName = (X500Name) caimpl.getIssuerDN(); + byte[] issuerByte = issuerName.getEncoded(); + ByteArrayInputStream istream = new ByteArrayInputStream(issuerByte); + Name issuer = (Name) Name.getTemplate().decode(istream); + IssuerAndSerialNumber ias = new IssuerAndSerialNumber( + issuer, new INTEGER(x509CAcert.getSerialNumber().toString())); + SignerIdentifier si = new SignerIdentifier( + SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null); + // use CA instance's default signature and digest algorithm + SignatureAlgorithm signAlg = ca.getDefaultSignatureAlgorithm(); + org.mozilla.jss.crypto.PrivateKey privKey = + CryptoManager.getInstance().findPrivKeyByCert(x509CAcert); + /* + org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType(); + if( keyType.equals( org.mozilla.jss.crypto.PrivateKey.RSA ) ) { + signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest; + } else if( keyType.equals( org.mozilla.jss.crypto.PrivateKey.DSA ) ) { + signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest; + } else if( keyType.equals( org.mozilla.jss.crypto.PrivateKey.EC ) ) { + signAlg = SignatureAlgorithm.ECSignatureWithSHA1Digest; + } else { + CMS.debug( "CMCOutputTemplate::getContentInfo() - " + + "signAlg is unsupported!" ); + return null; + } + */ + DigestAlgorithm digestAlg = signAlg.getDigestAlg(); + MessageDigest msgDigest = null; + byte[] digest = null; + + msgDigest = MessageDigest.getInstance(digestAlg.toString()); + + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + respBody.encode((OutputStream) ostream); + digest = msgDigest.digest(ostream.toByteArray()); + + SignerInfo signInfo = new + SignerInfo(si, null, null, + OBJECT_IDENTIFIER.id_cct_PKIResponse, + digest, signAlg, privKey); + SET signInfos = new SET(); + + signInfos.addElement(signInfo); + + SET digestAlgs = new SET(); + + if (digestAlg != null) { + AlgorithmIdentifier ai = new + AlgorithmIdentifier(digestAlg.toOID(), null); + + digestAlgs.addElement(ai); + } + SignedData signedData = new SignedData(digestAlgs, + enContentInfo, certs, null, signInfos); + + ContentInfo contentInfo = new ContentInfo(signedData); + CMS.debug("CMCOutputTemplate::getContentInfo() - done"); + return contentInfo; + } catch (Exception e) { + CMS.debug("CMCOutputTemplate: Failed to create CMCContentInfo. Exception: " + e.toString()); + } + return null; + } + + public void createSimpleResponse(HttpServletResponse resp, IRequest[] reqs) { + SET certs = new SET(); + SessionContext context = SessionContext.getContext(); + try { + TaggedAttribute attr = + (TaggedAttribute) (context.get(OBJECT_IDENTIFIER.id_cmc_getCert)); + processGetCertControl(attr, certs); + } catch (Exception e) { + CMS.debug("CMCOutputTemplate: No certificate is found."); + } + + SET digestAlgorithms = new SET(); + SET signedInfos = new SET(); + + // oid for id-data + OBJECT_IDENTIFIER oid = new OBJECT_IDENTIFIER("1.2.840.113549.1.7.1"); + EncapsulatedContentInfo enContentInfo = new EncapsulatedContentInfo(oid, null); + + try { + if (reqs != null) { + for (int i = 0; i < reqs.length; i++) { + X509CertImpl impl = + (reqs[i].getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT)); + byte[] bin = impl.getEncoded(); + Certificate.Template certTemplate = new Certificate.Template(); + Certificate cert = + (Certificate) certTemplate.decode(new ByteArrayInputStream(bin)); + + certs.addElement(cert); + } + + // Get CA certs + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + CertificateChain certchains = ca.getCACertChain(); + java.security.cert.X509Certificate[] chains = certchains.getChain(); + + for (int i = 0; i < chains.length; i++) { + Certificate.Template certTemplate = new Certificate.Template(); + Certificate cert = (Certificate) certTemplate.decode( + new ByteArrayInputStream(chains[i].getEncoded())); + certs.addElement(cert); + } + } + + if (certs.size() == 0) + return; + SignedData signedData = new SignedData(digestAlgorithms, + enContentInfo, certs, null, signedInfos); + + ContentInfo contentInfo = new ContentInfo(signedData); + ByteArrayOutputStream fos = new ByteArrayOutputStream(); + contentInfo.encode(fos); + fos.close(); + byte[] contentBytes = fos.toByteArray(); + + resp.setContentType("application/pkcs7-mime"); + resp.setContentLength(contentBytes.length); + OutputStream os = resp.getOutputStream(); + os.write(contentBytes); + os.flush(); + } catch (java.security.cert.CertificateEncodingException e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); + } catch (InvalidBERException e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); + } catch (IOException e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); + } + } + + private int processConfirmCertAcceptanceControl( + TaggedAttribute attr, SEQUENCE controlSeq, int bpid) { + if (attr != null) { + INTEGER bodyId = attr.getBodyPartID(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(bodyId); + SET values = attr.getValues(); + if (values != null && values.size() > 0) { + try { + CMCCertId cmcCertId = + (CMCCertId) (ASN1Util.decode(CMCCertId.getTemplate(), + ASN1Util.encode(values.elementAt(0)))); + BigInteger serialno = (BigInteger) (cmcCertId.getSerial()); + SEQUENCE issuers = cmcCertId.getIssuer(); + //ANY issuer = (ANY)issuers.elementAt(0); + ANY issuer = + (ANY) (ASN1Util.decode(ANY.getTemplate(), + ASN1Util.encode(issuers.elementAt(0)))); + byte[] b = issuer.getEncoded(); + X500Name n = new X500Name(b); + ICertificateAuthority ca = null; + ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + X500Name caName = ca.getX500Name(); + boolean confirmAccepted = false; + if (n.toString().equalsIgnoreCase(caName.toString())) { + CMS.debug("CMCOutputTemplate: Issuer names are equal"); + ICertificateRepository repository = + (ICertificateRepository) ca.getCertificateRepository(); + try { + repository.getX509Certificate(serialno); + } catch (EBaseException ee) { + CMS.debug("CMCOutputTemplate: Certificate in the confirm acceptance control was not found"); + } + } + CMCStatusInfo cmcStatusInfo = null; + if (confirmAccepted) { + CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate exists in the certificate repository."); + cmcStatusInfo = + new CMCStatusInfo(CMCStatusInfo.SUCCESS, seq, + (String) null, null); + } else { + CMS.debug("CMCOutputTemplate: Confirm Acceptance received. The certificate does not exist in the certificate repository."); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, + new INTEGER(OtherInfo.BAD_CERT_ID), null); + cmcStatusInfo = + new CMCStatusInfo(CMCStatusInfo.FAILED, seq, + (String) null, otherInfo); + } + TaggedAttribute statustagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(statustagattr); + } catch (Exception e) { + CMS.debug("CMCOutputTemplate exception: " + e.toString()); + } + } + } + return bpid; + } + + private void processGetCertControl(TaggedAttribute attr, SET certs) + throws InvalidBERException, java.security.cert.CertificateEncodingException, + IOException, EBaseException { + if (attr != null) { + SET vals = attr.getValues(); + + if (vals.size() == 1) { + GetCert getCert = + (GetCert) (ASN1Util.decode(GetCert.getTemplate(), + ASN1Util.encode(vals.elementAt(0)))); + BigInteger serialno = (BigInteger) (getCert.getSerialNumber()); + ANY issuer = (ANY) getCert.getIssuer(); + byte b[] = issuer.getEncoded(); + X500Name n = new X500Name(b); + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + X500Name caName = ca.getX500Name(); + if (!n.toString().equalsIgnoreCase(caName.toString())) { + CMS.debug("CMCOutputTemplate: Issuer names are equal in the GetCert Control"); + throw new EBaseException("Certificate is not found"); + } + ICertificateRepository repository = + (ICertificateRepository) ca.getCertificateRepository(); + X509CertImpl impl = repository.getX509Certificate(serialno); + byte[] bin = impl.getEncoded(); + Certificate.Template certTemplate = new Certificate.Template(); + Certificate cert = + (Certificate) certTemplate.decode(new ByteArrayInputStream(bin)); + certs.addElement(cert); + } + } + } + + private int processQueryPendingControl(TaggedAttribute attr, + SEQUENCE controlSeq, int bpid) { + if (attr != null) { + SET values = attr.getValues(); + if (values != null && values.size() > 0) { + SEQUENCE pending_bpids = new SEQUENCE(); + SEQUENCE success_bpids = new SEQUENCE(); + SEQUENCE failed_bpids = new SEQUENCE(); + for (int i = 0; i < values.size(); i++) { + try { + INTEGER reqId = (INTEGER) + ASN1Util.decode(INTEGER.getTemplate(), + ASN1Util.encode(values.elementAt(i))); + String requestId = new String(reqId.toByteArray()); + + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + IRequestQueue queue = ca.getRequestQueue(); + IRequest r = queue.findRequest(new RequestId(requestId)); + if (r != null) { + RequestStatus status = r.getRequestStatus(); + if (status.equals(RequestStatus.PENDING)) { + pending_bpids.addElement(reqId); + } else if (status.equals(RequestStatus.APPROVED)) { + success_bpids.addElement(reqId); + } else if (status.equals(RequestStatus.REJECTED)) { + failed_bpids.addElement(reqId); + } + } + } catch (Exception e) { + } + } + + if (pending_bpids.size() > 0) { + CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.PENDING, + pending_bpids, (String) null, null); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + if (success_bpids.size() > 0) { + CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, + pending_bpids, (String) null, null); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + + if (failed_bpids.size() > 0) { + CMCStatusInfo cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, + pending_bpids, (String) null, null); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + } + + } + } + return bpid; + } + + private int processTransactionControl(TaggedAttribute attr, + SEQUENCE controlSeq, int bpid) { + if (attr != null) { + SET transIds = attr.getValues(); + if (transIds != null) { + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_transactionId, + transIds); + controlSeq.addElement(tagattr); + } + } + + return bpid; + } + + private int processSenderNonceControl(TaggedAttribute attr, + SEQUENCE controlSeq, int bpid) { + if (attr != null) { + SET sNonce = attr.getValues(); + if (sNonce != null) { + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_recipientNonce, + sNonce); + controlSeq.addElement(tagattr); + Date date = new Date(); + String salt = "lala123" + date.toString(); + byte[] dig; + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + dig = SHA1Digest.digest(salt.getBytes()); + } catch (NoSuchAlgorithmException ex) { + dig = salt.getBytes(); + } + + String b64E = CMS.BtoA(dig); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), OBJECT_IDENTIFIER.id_cmc_senderNonce, + new OCTET_STRING(b64E.getBytes())); + controlSeq.addElement(tagattr); + } + } + + return bpid; + } + + private int processDataReturnControl(TaggedAttribute attr, + SEQUENCE controlSeq, int bpid) throws InvalidBERException { + + if (attr != null) { + SET vals = attr.getValues(); + + if (vals.size() > 0) { + OCTET_STRING str = + (OCTET_STRING) (ASN1Util.decode(OCTET_STRING.getTemplate(), + ASN1Util.encode(vals.elementAt(0)))); + TaggedAttribute tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_dataReturn, str); + controlSeq.addElement(tagattr); + } + } + + return bpid; + } + + private int processRevokeRequestControl(TaggedAttribute attr, + SEQUENCE controlSeq, int bpid) throws InvalidBERException, EBaseException, + IOException { + boolean revoke = false; + SessionContext context = SessionContext.getContext(); + if (attr != null) { + INTEGER attrbpid = attr.getBodyPartID(); + CMCStatusInfo cmcStatusInfo = null; + SET vals = attr.getValues(); + if (vals.size() > 0) { + RevRequest revRequest = + (RevRequest) (ASN1Util.decode(new RevRequest.Template(), + ASN1Util.encode(vals.elementAt(0)))); + OCTET_STRING str = revRequest.getSharedSecret(); + INTEGER pid = attr.getBodyPartID(); + TaggedAttribute tagattr = null; + INTEGER revokeCertSerial = revRequest.getSerialNumber(); + BigInteger revokeSerial = new BigInteger(revokeCertSerial.toByteArray()); + if (str == null) { + boolean needVerify = true; + try { + needVerify = CMS.getConfigStore().getBoolean("cmc.revokeCert.verify", true); + } catch (Exception e) { + } + + if (needVerify) { + Integer num1 = (Integer) context.get("numOfOtherMsgs"); + int num = num1.intValue(); + for (int i = 0; i < num; i++) { + OtherMsg data = (OtherMsg) context.get("otherMsg" + i); + INTEGER dpid = data.getBodyPartID(); + if (pid.longValue() == dpid.longValue()) { + ANY msgValue = data.getOtherMsgValue(); + SignedData msgData = + (SignedData) msgValue.decodeWith(SignedData.getTemplate()); + if (!verifyRevRequestSignature(msgData)) { + OtherInfo otherInfo = + new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), + null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfo = + new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, + otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + } + } + } + + revoke = true; + // check shared secret + } else { + ISharedToken tokenClass = null; + boolean sharedSecretFound = true; + String name = null; + try { + name = CMS.getConfigStore().getString("cmc.revokeCert.sharedSecret.class"); + } catch (EPropertyNotFound e) { + CMS.debug("EnrollProfile: Failed to find the token class in the configuration file."); + sharedSecretFound = false; + } catch (EBaseException e) { + CMS.debug("EnrollProfile: Failed to find the token class in the configuration file."); + sharedSecretFound = false; + } + + try { + tokenClass = (ISharedToken) Class.forName(name).newInstance(); + } catch (ClassNotFoundException e) { + CMS.debug("EnrollProfile: Failed to find class name: " + name); + sharedSecretFound = false; + } catch (InstantiationException e) { + CMS.debug("EnrollProfile: Failed to instantiate class: " + name); + sharedSecretFound = false; + } catch (IllegalAccessException e) { + CMS.debug("EnrollProfile: Illegal access: " + name); + sharedSecretFound = false; + } + + if (!sharedSecretFound) { + CMS.debug("CMCOutputTemplate: class for shared secret was not found."); + OtherInfo otherInfo = + new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + + String sharedSecret = null; + if (tokenClass != null) { + sharedSecret = tokenClass.getSharedToken(revokeSerial); + } + + if (sharedSecret == null) { + CMS.debug("CMCOutputTemplate: class for shared secret was not found."); + OtherInfo otherInfo = + new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.INTERNAL_CA_ERROR), null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + + byte[] strb = str.toByteArray(); + String clientSC = new String(strb); + if (clientSC.equals(sharedSecret)) { + CMS.debug("CMCOutputTemplate: Both client and server shared secret are the same, can go ahead to revoke certificate."); + revoke = true; + } else { + CMS.debug("CMCOutputTemplate: Both client and server shared secret are not the same, cant revoke certificate."); + OtherInfo otherInfo = + new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + } + + if (revoke) { + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + ICertificateRepository repository = (ICertificateRepository) ca.getCertificateRepository(); + ICertRecord record = null; + try { + record = repository.readCertificateRecord(revokeSerial); + } catch (EBaseException ee) { + CMS.debug("CMCOutputTemplate: Exception: " + ee.toString()); + } + + if (record == null) { + CMS.debug("CMCOutputTemplate: The certificate is not found"); + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_CERT_ID), null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + + if (record.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + CMS.debug("CMCOutputTemplate: The certificate is already revoked."); + SEQUENCE success_bpids = new SEQUENCE(); + success_bpids.addElement(attrbpid); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, + success_bpids, (String) null, null); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + X509CertImpl impl = record.getCertificate(); + X509CertImpl[] impls = new X509CertImpl[1]; + impls[0] = impl; + ENUMERATED n = revRequest.getReason(); + RevocationReason reason = toRevocationReason(n); + CRLReasonExtension crlReasonExtn = new CRLReasonExtension(reason); + CRLExtensions entryExtn = new CRLExtensions(); + GeneralizedTime t = revRequest.getInvalidityDate(); + InvalidityDateExtension invalidityDateExtn = null; + if (t != null) { + invalidityDateExtn = new InvalidityDateExtension(t.toDate()); + entryExtn.set(invalidityDateExtn.getName(), invalidityDateExtn); + } + if (crlReasonExtn != null) { + entryExtn.set(crlReasonExtn.getName(), crlReasonExtn); + } + + RevokedCertImpl revCertImpl = + new RevokedCertImpl(impl.getSerialNumber(), CMS.getCurrentDate(), entryExtn); + RevokedCertImpl[] revCertImpls = new RevokedCertImpl[1]; + revCertImpls[0] = revCertImpl; + IRequestQueue queue = ca.getRequestQueue(); + IRequest revReq = queue.newRequest(IRequest.REVOCATION_REQUEST); + revReq.setExtData(IRequest.CERT_INFO, revCertImpls); + revReq.setExtData(IRequest.REVOKED_REASON, + Integer.valueOf(reason.toInt())); + UTF8String utfstr = revRequest.getComment(); + if (utfstr != null) + revReq.setExtData(IRequest.REQUESTOR_COMMENTS, utfstr.toString()); + revReq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_AGENT); + queue.processRequest(revReq); + RequestStatus stat = revReq.getRequestStatus(); + if (stat == RequestStatus.COMPLETE) { + Integer result = revReq.getExtDataInInteger(IRequest.RESULT); + CMS.debug("CMCOutputTemplate: revReq result = " + result); + if (result.equals(IRequest.RES_ERROR)) { + CMS.debug("CMCOutputTemplate: revReq exception: " + + revReq.getExtDataInString(IRequest.ERROR)); + OtherInfo otherInfo = + new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_REQUEST), null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfo = + new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + } + + ILogger logger = CMS.getLogger(); + String initiative = AuditFormat.FROMUSER; + logger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, new Object[] { + revReq.getRequestId(), initiative, "completed", + impl.getSubjectDN(), + impl.getSerialNumber().toString(16), + reason.toString() }); + CMS.debug("CMCOutputTemplate: Certificate get revoked."); + SEQUENCE success_bpids = new SEQUENCE(); + success_bpids.addElement(attrbpid); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.SUCCESS, + success_bpids, (String) null, null); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } else { + OtherInfo otherInfo = new OtherInfo(OtherInfo.FAIL, new INTEGER(OtherInfo.BAD_MESSAGE_CHECK), null); + SEQUENCE failed_bpids = new SEQUENCE(); + failed_bpids.addElement(attrbpid); + cmcStatusInfo = new CMCStatusInfo(CMCStatusInfo.FAILED, failed_bpids, (String) null, otherInfo); + tagattr = new TaggedAttribute( + new INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, cmcStatusInfo); + controlSeq.addElement(tagattr); + return bpid; + } + } + } + + return bpid; + } + + private RevocationReason toRevocationReason(ENUMERATED n) { + long code = n.getValue(); + if (code == RevRequest.aACompromise.getValue()) + return RevocationReason.UNSPECIFIED; + else if (code == RevRequest.affiliationChanged.getValue()) + return RevocationReason.AFFILIATION_CHANGED; + else if (code == RevRequest.cACompromise.getValue()) + return RevocationReason.CA_COMPROMISE; + else if (code == RevRequest.certificateHold.getValue()) + return RevocationReason.CERTIFICATE_HOLD; + else if (code == RevRequest.cessationOfOperation.getValue()) + return RevocationReason.CESSATION_OF_OPERATION; + else if (code == RevRequest.keyCompromise.getValue()) + return RevocationReason.KEY_COMPROMISE; + else if (code == RevRequest.privilegeWithdrawn.getValue()) + return RevocationReason.UNSPECIFIED; + else if (code == RevRequest.removeFromCRL.getValue()) + return RevocationReason.REMOVE_FROM_CRL; + else if (code == RevRequest.superseded.getValue()) + return RevocationReason.SUPERSEDED; + else if (code == RevRequest.unspecified.getValue()) + return RevocationReason.UNSPECIFIED; + return RevocationReason.UNSPECIFIED; + } + + private boolean verifyRevRequestSignature(SignedData msgData) { + try { + EncapsulatedContentInfo ci = msgData.getContentInfo(); + OCTET_STRING content = ci.getContent(); + ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray()); + TaggedAttribute tattr = (TaggedAttribute) (new TaggedAttribute.Template()).decode(s); + SET values = tattr.getValues(); + RevRequest revRequest = null; + if (values != null && values.size() > 0) + revRequest = + (RevRequest) (ASN1Util.decode(new RevRequest.Template(), + ASN1Util.encode(values.elementAt(0)))); + + SET dias = msgData.getDigestAlgorithmIdentifiers(); + int numDig = dias.size(); + Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>(); + for (int i = 0; i < numDig; i++) { + AlgorithmIdentifier dai = + (AlgorithmIdentifier) dias.elementAt(i); + String name = + DigestAlgorithm.fromOID(dai.getOID()).toString(); + MessageDigest md = + MessageDigest.getInstance(name); + byte[] digest = md.digest(content.toByteArray()); + digs.put(name, digest); + } + + SET sis = msgData.getSignerInfos(); + int numSis = sis.size(); + for (int i = 0; i < numSis; i++) { + org.mozilla.jss.pkix.cms.SignerInfo si = + (org.mozilla.jss.pkix.cms.SignerInfo) sis.elementAt(i); + String name = si.getDigestAlgorithm().toString(); + byte[] digest = digs.get(name); + if (digest == null) { + MessageDigest md = MessageDigest.getInstance(name); + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + revRequest.encode((OutputStream) ostream); + digest = md.digest(ostream.toByteArray()); + } + SignerIdentifier sid = si.getSignerIdentifier(); + if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) { + org.mozilla.jss.pkix.cms.IssuerAndSerialNumber issuerAndSerialNumber = + sid.getIssuerAndSerialNumber(); + java.security.cert.X509Certificate cert = null; + if (msgData.hasCertificates()) { + SET certs = msgData.getCertificates(); + int numCerts = certs.size(); + for (int j = 0; j < numCerts; j++) { + org.mozilla.jss.pkix.cert.Certificate certJss = + (Certificate) certs.elementAt(j); + org.mozilla.jss.pkix.cert.CertificateInfo certI = + certJss.getInfo(); + Name issuer = certI.getIssuer(); + byte[] issuerB = ASN1Util.encode(issuer); + INTEGER sn = certI.getSerialNumber(); + if (new String(issuerB).equalsIgnoreCase(new String(ASN1Util.encode(issuerAndSerialNumber + .getIssuer()))) && + sn.toString().equals(issuerAndSerialNumber.getSerialNumber().toString())) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + certJss.encode(os); + cert = new X509CertImpl(os.toByteArray()); + break; + } + } + } + + if (cert != null) { + PublicKey pbKey = cert.getPublicKey(); + String type = ((X509Key) pbKey).getAlgorithm(); + PrivateKey.Type kType = PrivateKey.RSA; + if (type.equals("DSA")) + kType = PrivateKey.DSA; + PK11PubKey pubK = PK11PubKey.fromRaw(kType, ((X509Key) pbKey).getKey()); + si.verify(digest, ci.getContentType(), pubK); + return true; + } + } + } + + return false; + } catch (Exception e) { + CMS.debug("CMCOutputTemplate: verifyRevRequestSignature. Exception: " + e.toString()); + return false; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSFile.java b/base/common/src/com/netscape/cms/servlet/common/CMSFile.java new file mode 100644 index 000000000..4d7c4cdd6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSFile.java @@ -0,0 +1,102 @@ +// --- 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.common; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; + +/** + * CMSFile represents a file from the filesystem cached in memory + * + * @version $Revision$, $Date$ + */ +public class CMSFile { + protected String mAbsPath; + protected long mLastModified; + protected byte[] mContent; + protected long mLastAccess = 0; + + protected ILogger mLogger = CMS.getLogger(); + + protected CMSFile() { + } + + public CMSFile(File file) throws IOException, EBaseException { + mAbsPath = file.getAbsolutePath(); + mLastModified = file.lastModified(); + fillContent(file); + } + + private void fillContent(File file) throws IOException { + int fileSize = (int) file.length(); + + mContent = new byte[fileSize]; + FileInputStream fileIn = new FileInputStream(file); + int actualSize = fileIn.read(mContent); + fileIn.close(); + + if (actualSize != fileSize) { + byte[] actualContent = new byte[actualSize]; + + System.arraycopy(mContent, 0, actualContent, 0, actualSize); + mContent = actualContent; + } + } + + public String getAbsPath() { + return mAbsPath; + } + + public byte[] getContent() { + return mContent; + } + + public long getLastModified() { + return mLastModified; + } + + public synchronized long getLastAccess() { + return mLastAccess; + } + + public synchronized void setLastAccess(long lastAccess) { + mLastAccess = lastAccess; + } + + protected void log(int level, String msg) { + mLogger.log(ILogger.EV_SYSTEM, level, ILogger.S_OTHER, "CMSgateway:" + msg); + } + + public String toString() { + try { + return new String(mContent, "UTF8"); + } catch (UnsupportedEncodingException e) { + return new String(mContent); + } + } + + public String toString(String enc) throws UnsupportedEncodingException { + return new String(mContent, enc); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSFileLoader.java b/base/common/src/com/netscape/cms/servlet/common/CMSFileLoader.java new file mode 100644 index 000000000..808bdda78 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSFileLoader.java @@ -0,0 +1,160 @@ +// --- 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.common; + +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; + +/** + * CMSFileLoader - file cache. + * + * @version $Revision$, $Date$ + */ + +public class CMSFileLoader { + // default max size + public final int MAX_SIZE = 200; + // default number of files to clear when max is reached. + public final int CLEAR_SIZE = 50; + // max size property + public final String PROP_MAX_SIZE = "maxSize"; + // clear size property + public final String PROP_CLEAR_SIZE = "clearSize"; + // property to cache templates only + public final String PROP_CACHE_TEMPLATES_ONLY = "cacheTemplatesOnly"; + + // hash of files to their content. + private Hashtable<String, CMSFile> mLoadedFiles = new Hashtable<String, CMSFile>(); + + // max number of files + private int mMaxSize = MAX_SIZE; + + // number of files to clear when max is reached. + private int mClearSize = CLEAR_SIZE; + + // whether to cache templates and forms only. + private boolean mCacheTemplatesOnly = true; + + public CMSFileLoader() { + } + + public void init(IConfigStore config) throws EBaseException { + mMaxSize = config.getInteger(PROP_MAX_SIZE, MAX_SIZE); + mClearSize = config.getInteger(PROP_CLEAR_SIZE, CLEAR_SIZE); + mCacheTemplatesOnly = + config.getBoolean(PROP_CACHE_TEMPLATES_ONLY, true); + } + + // Changed by bskim + //public byte[] get(String absPath) throws EBaseException, IOException { + // File file = new File(absPath); + // return get(file); + //} + public byte[] get(String absPath, String enc) throws EBaseException, IOException { + File file = new File(absPath); + + return get(file, enc); + } + + // Change end + + // Changed by bskim + //public byte[] get(File file) throws EBaseException, IOException { + // CMSFile cmsFile = getCMSFile(file); + public byte[] get(File file, String enc) throws EBaseException, IOException { + CMSFile cmsFile = getCMSFile(file, enc); + + // Change end + return cmsFile.getContent(); + } + + // Changed by bskim + //public CMSFile getCMSFile(File file) throws EBaseException, IOException { + public CMSFile getCMSFile(File file, String enc) throws EBaseException, IOException { + // Change end + String absPath = file.getAbsolutePath(); + long modified = file.lastModified(); + CMSFile cmsFile = (CMSFile) mLoadedFiles.get(absPath); + long lastModified = (cmsFile == null ? 0 : cmsFile.getLastModified()); + + // new file. + if (cmsFile == null || modified != lastModified) { + // Changed by bskim + //cmsFile = updateFile(absPath, file); + cmsFile = updateFile(absPath, file, enc); + // Change end + } + cmsFile.setLastAccess(System.currentTimeMillis()); + return cmsFile; + } + + // Changed by bskim + //private CMSFile updateFile(String absPath, File file) + private CMSFile updateFile(String absPath, File file, String enc) + // Change end + throws EBaseException, IOException { + // clear if cache size exceeded. + if (mLoadedFiles.size() >= mMaxSize) { + clearSomeFiles(); + } + + CMSFile cmsFile = null; + + // check if file is a js template or plain template by its first String + if (absPath.endsWith(CMSTemplate.SUFFIX)) { + // Changed by bskim + //cmsFile = new CMSTemplate(file); + cmsFile = new CMSTemplate(file, enc); + // End of Change + } else { + cmsFile = new CMSFile(file); + } + mLoadedFiles.put(absPath, cmsFile); // replace old one if any. + return cmsFile; + } + + private synchronized void clearSomeFiles() { + + // recheck this in case some other thread has cleared it. + if (mLoadedFiles.size() < mMaxSize) + return; + + // remove the LRU files. + // XXX could be optimized more. + Enumeration<CMSFile> elements = mLoadedFiles.elements(); + + for (int i = mClearSize; i > 0; i--) { + long lru = java.lang.Long.MAX_VALUE; + CMSFile lruFile = null; + + while (elements.hasMoreElements()) { + CMSFile cmsFile = elements.nextElement(); + + if (cmsFile.getLastAccess() < lru) { + lruFile = cmsFile; + } + mLoadedFiles.remove(lruFile.getAbsPath()); + } + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSGWResources.java b/base/common/src/com/netscape/cms/servlet/common/CMSGWResources.java new file mode 100644 index 000000000..7ae242ae7 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSGWResources.java @@ -0,0 +1,44 @@ +// --- 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.common; + +import java.util.ListResourceBundle; + +/** + * A class represents a resource bundle for cms gateway. + * <P> + * + * @version $Revision$, $Date$ + * @see java.util.ListResourceBundle + */ +public class CMSGWResources extends ListResourceBundle { + + /** + * Returns the content of this resource. + */ + public Object[][] getContents() { + return contents; + } + + /* + * Constants. The suffix represents the number of + * possible parameters. + */ + + static final Object[][] contents = {}; +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSGateway.java b/base/common/src/com/netscape/cms/servlet/common/CMSGateway.java new file mode 100644 index 000000000..20743022a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSGateway.java @@ -0,0 +1,372 @@ +// --- 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.common; + +import java.io.File; +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthCredentials; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; + +/** + * This class is to hold some general method for servlets. + * + * @version $Revision$, $Date$ + */ +public class CMSGateway { + public final static String PROP_CMSGATEWAY = "cmsgateway"; + private final static String PROP_ENABLE_ADMIN_ENROLL = "enableAdminEnroll"; + + private final static String PROP_SERVER_XML = "server.xml"; + public static final String CERT_ATTR = + "javax.servlet.request.X509Certificate"; + + protected static CMSFileLoader mFileLoader = new CMSFileLoader(); + + protected static boolean mEnableFileServing; + private static boolean mEnableAdminEnroll = true; + private static IConfigStore mConfig = null; + + // system logger. + protected static ILogger mLogger = CMS.getLogger(); + + static { + mEnableFileServing = true; + mConfig = CMS.getConfigStore().getSubStore(PROP_CMSGATEWAY); + try { + mEnableAdminEnroll = + mConfig.getBoolean(PROP_ENABLE_ADMIN_ENROLL, false); + } catch (EBaseException e) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_BAD_CONFIG_PARAM")); + } + } + + public CMSGateway() { + } + + public static Hashtable<String, String> toHashtable(HttpServletRequest req) { + Hashtable<String, String> httpReqHash = new Hashtable<String, String>(); + @SuppressWarnings("unchecked") + Enumeration<String> names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = names.nextElement(); + + httpReqHash.put(name, req.getParameter(name)); + } + + String ip = req.getRemoteAddr(); + if (ip != null) + httpReqHash.put("clientHost", ip); + return httpReqHash; + } + + public static boolean getEnableAdminEnroll() { + return mEnableAdminEnroll; + } + + public static void setEnableAdminEnroll(boolean enableAdminEnroll) + throws EBaseException { + IConfigStore mainConfig = CMS.getConfigStore(); + + //!!! Is it thread safe? xxxx + mEnableAdminEnroll = enableAdminEnroll; + mConfig.putBoolean(PROP_ENABLE_ADMIN_ENROLL, enableAdminEnroll); + mainConfig.commit(true); + } + + public static void disableAdminEnroll() throws EBaseException { + setEnableAdminEnroll(false); + + /* need to do this in web.xml and restart ws + removeServlet("/ca/adminEnroll", "AdminEnroll"); + initGateway(); + */ + } + + /** + * construct a authentication credentials to pass into authentication + * manager. + */ + public static AuthCredentials getAuthCreds( + IAuthManager authMgr, IArgBlock argBlock, X509Certificate clientCert) + throws EBaseException { + // get credentials from http parameters. + if (authMgr == null) + return null; + String[] reqCreds = authMgr.getRequiredCreds(); + AuthCredentials creds = new AuthCredentials(); + + if (clientCert instanceof java.security.cert.X509Certificate) { + try { + clientCert = new netscape.security.x509.X509CertImpl(clientCert.getEncoded()); + } catch (Exception e) { + CMS.debug("CMSGateway: getAuthCreds " + e.toString()); + } + } + + for (int i = 0; i < reqCreds.length; i++) { + String reqCred = reqCreds[i]; + + if (reqCred.equals(IAuthManager.CRED_SSL_CLIENT_CERT)) { + // cert could be null; + creds.set(reqCred, new X509Certificate[] { clientCert } + ); + } else { + String value = argBlock.getValueAsString(reqCred); + + creds.set(reqCred, value); // value could be null; + } + } + + creds.set("clientHost", argBlock.getValueAsString("clientHost")); + // Inserted by bskim + creds.setArgBlock(argBlock); + // Insert end + return creds; + } + + protected final static String AUTHMGR_PARAM = "authenticator"; + + public static AuthToken checkAuthManager( + HttpServletRequest httpReq, IArgBlock httpParams, + X509Certificate cert, String authMgrName) + throws EBaseException { + IArgBlock httpArgs = httpParams; + + if (httpArgs == null) + httpArgs = CMS.createArgBlock(toHashtable(httpReq)); + + IAuthSubsystem authSub = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + + String authMgr_http = httpArgs.getValueAsString( + AUTHMGR_PARAM, null); + + if (authMgr_http != null) { + authMgrName = authMgr_http; + } + + if (authMgrName == null || authMgrName.length() == 0) { + throw new EBaseException(CMS.getLogMessage("BASE_INTERNAL_ERROR_1", + CMS.getLogMessage("CMSGW_AUTH_MAN_EXPECTED"))); + } + + IAuthManager authMgr = + authSub.getAuthManager(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID); + + authMgr = authSub.getAuthManager(authMgrName); + if (authMgr == null) + return null; + IAuthCredentials creds = + getAuthCreds(authMgr, CMS.createArgBlock(toHashtable(httpReq)), cert); + AuthToken authToken = null; + + try { + authToken = (AuthToken) authMgr.authenticate(creds); + } catch (EBaseException e) { + throw e; + } catch (Exception e) { + CMS.debug("CMSGateway: " + e); + // catch all errors from authentication manager. + throw new ECMSGWException(CMS.getLogMessage("CMSGW_AUTH_ERROR_2", + e.toString(), e.getMessage())); + } + return authToken; + } + + public static void renderTemplate( + String templateName, + HttpServletRequest req, + HttpServletResponse resp, + ServletConfig servletConfig, + CMSFileLoader fileLoader) + throws EBaseException, IOException { + CMSTemplate template = + getTemplate(templateName, req, + servletConfig, fileLoader, new Locale[1]); + ServletOutputStream out = resp.getOutputStream(); + + template.renderOutput(out, new CMSTemplateParams(null, null)); + } + + // XXX TBD move this to a utility function too. + + public static Locale getLocale(String lang) { + int dash = lang.indexOf('-'); + + if (dash == -1) + return new Locale(lang, ""); + else + return new Locale(lang.substring(0, dash), lang.substring(dash + 1)); + } + + /** + * @param req http servlet request + * @param realpathFile the file to get. + * @param locale array of at least one to be filled with locale found. + */ + public static File getLangFile( + HttpServletRequest req, File realpathFile, Locale[] locale) + throws IOException { + File file = null; + String acceptLang = req.getHeader("accept-language"); + + if (acceptLang != null && !acceptLang.equals("")) { + StringTokenizer tokenizer = new StringTokenizer(acceptLang, ","); + int numLangs = tokenizer.countTokens(); + + if (numLangs > 0) { + // languages are searched in order. + String parent = realpathFile.getParent(); + + if (parent == null) { + parent = "." + File.separatorChar; + } + String name = realpathFile.getName(); + + if (name == null) { // filename should never be null. + throw new IOException("file has no name"); + } + int i; + + for (i = 0; i < numLangs; i++) { + String lang = null; + String token = tokenizer.nextToken(); + + int semicolon = token.indexOf(';'); + + if (semicolon == -1) { + lang = token.trim(); + } else { + if (semicolon < 2) + continue; // protocol error. + lang = token.substring(0, semicolon).trim(); + } + // if browser locale is the same as default locale, + // use the default form. (is this the right thing to do ?) + Locale l = getLocale(lang); + + if (Locale.getDefault().equals(l)) { + locale[0] = l; + file = realpathFile; + break; + } + + String langfilepath = + parent + File.separatorChar + + lang + File.separatorChar + name; + + file = new File(langfilepath); + if (file.exists()) { + locale[0] = getLocale(lang); + break; + } + } + // if no file for lang was found use default + if (i == numLangs) { + file = realpathFile; + locale[0] = Locale.getDefault(); + } + } + } else { + // use default if accept-language is not availabe + file = realpathFile; + locale[0] = Locale.getDefault(); + } + return file; + } + + /** + * get a template + */ + protected static CMSTemplate getTemplate( + String templateName, + HttpServletRequest httpReq, + ServletConfig servletConfig, + CMSFileLoader fileLoader, + Locale[] locale) + throws EBaseException, IOException { + // this converts to system dependent file seperator char. + if (servletConfig == null) { + CMS.debug("CMSGateway:getTemplate() - servletConfig is null!"); + return null; + } + if (servletConfig.getServletContext() == null) { + } + if (templateName == null) { + } + String realpath = + servletConfig.getServletContext().getRealPath("/" + templateName); + File realpathFile = new File(realpath); + File templateFile = + getLangFile(httpReq, realpathFile, locale); + CMSTemplate template = + //(CMSTemplate)fileLoader.getCMSFile(templateFile); + (CMSTemplate) fileLoader.getCMSFile(templateFile, httpReq.getCharacterEncoding()); + + return template; + } + + /** + * Get the If-Modified-Since header and compare it to the millisecond + * epoch value passed in. If there is no header, or there is a problem + * parsing the value, or if the file has been modified this will return + * true, indicating the file has changed. + * + * @param lastModified The time value in milliseconds past the epoch to + * compare the If-Modified-Since header to. + */ + public static boolean modifiedSince(HttpServletRequest req, long lastModified) { + long ifModSinceStr; + + try { + ifModSinceStr = req.getDateHeader("If-Modified-Since"); + } catch (IllegalArgumentException e) { + return true; + } + + if (ifModSinceStr < 0) { + return true; + } + + if (ifModSinceStr < lastModified) { + return true; // Data must be resent + } + + return false; // Data has not been modified + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java b/base/common/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java new file mode 100644 index 000000000..62276df14 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java @@ -0,0 +1,60 @@ +// --- 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.common; + +/** + * handy class containing cms templates to load & fill. + * + * @version $Revision$, $Date$ + */ +public class CMSLoadTemplate { + public String mPropName; + public String mFillerPropName; + public String mTemplateName; + public ICMSTemplateFiller mFiller; + + public CMSLoadTemplate() { + } + + public CMSLoadTemplate( + String propName, String fillerPropName, + String templateName, ICMSTemplateFiller filler) { + + mPropName = propName; + mFillerPropName = fillerPropName; + mTemplateName = templateName; + mFiller = filler; + } + + public String getPropName() { + return mPropName; + } + + public String getFillerPropName() { + return mFillerPropName; + } + + public String getTemplateName() { + return mTemplateName; + } + + public ICMSTemplateFiller getTemplateFiller() { + return mFiller; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSRequest.java b/base/common/src/com/netscape/cms/servlet/common/CMSRequest.java new file mode 100644 index 000000000..256c01010 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSRequest.java @@ -0,0 +1,300 @@ +// --- 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.common; + +import java.util.Hashtable; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; + +/** + * This represents a user request. + * + * @version $Revision$, $Date$ + */ +public class CMSRequest { + // statuses. the first two are out of band. + public static final Integer UNAUTHORIZED = Integer.valueOf(1); + public static final Integer SUCCESS = Integer.valueOf(2); + public static final Integer PENDING = Integer.valueOf(3); + public static final Integer SVC_PENDING = Integer.valueOf(4); + public static final Integer REJECTED = Integer.valueOf(5); + public static final Integer ERROR = Integer.valueOf(6); + public static final Integer EXCEPTION = Integer.valueOf(7); // unexpected error. + + private static final String RESULT = "cmsRequestResult"; + + // Reason message for request failure + private String reason = null; + + // http parameters - handier than getting directly from http request. + private IArgBlock mHttpParams = null; + + // http headers & other info. + private HttpServletRequest mHttpReq = null; + + // http response. + private HttpServletResponse mHttpResp = null; + + // http servlet config. + private ServletConfig mServletConfig = null; + + // http servlet context. + private ServletContext mServletContext = null; + + // permanent request in request queue. + private IRequest mRequest = null; + + // whether request processed successfully + private Integer mStatus = SUCCESS; + + // exception message containing error that occured. + // note exception could also be thrown seperately. + private String mError = null; + + // any error description. + private Vector<String> mErrorDescr = null; + + // any request resulting data; + Object mResult = null; + Hashtable<String, Object> mResults = new Hashtable<String, Object>(); + + /** + * Constructor + */ + public CMSRequest() { + } + + // set methods use by servlets. + + /** + * set the HTTP parameters + */ + public void setHttpParams(IArgBlock httpParams) { + mHttpParams = httpParams; + } + + /** + * set the Request aobject associated with this session + */ + public void setIRequest(IRequest request) { + mRequest = request; + } + + /** + * set the HTTP Request object associated with this session + */ + public void setHttpReq(HttpServletRequest httpReq) { + mHttpReq = httpReq; + } + + /** + * set the HTTP Response object which is used to create the + * HTTP response which is sent back to the user + */ + public void setHttpResp(HttpServletResponse httpResp) { + mHttpResp = httpResp; + } + + /** + * set the servlet configuration. The servlet configuration is + * read from the WEB-APPS/web.xml file under the <servlet> + * XML definition. The parameters are delimited by init-param + * param-name/param-value options as described in the servlet + * documentation. + */ + public void setServletConfig(ServletConfig servletConfig) { + mServletConfig = servletConfig; + } + + /* + * set the servlet context. the servletcontext has detail + * about the currently running request + */ + public void setServletContext(ServletContext servletContext) { + mServletContext = servletContext; + } + + /** + * Set request status. + * + * @param status request status. Allowed values are + * UNAUTHORIZED, SUCCESS, REJECTED, PENDING, ERROR, SVC_PENDING + * @throws IllegalArgumentException if status is not one of the above values + */ + public void setStatus(Integer status) { + if (!status.equals(UNAUTHORIZED) && + !status.equals(SUCCESS) && + !status.equals(REJECTED) && + !status.equals(PENDING) && + !status.equals(ERROR) && + !status.equals(SVC_PENDING) && + !status.equals(EXCEPTION)) { + throw new IllegalArgumentException(CMS.getLogMessage("CMSGW_BAD_REQ_STATUS")); + } + mStatus = status; + } + + public void setError(EBaseException error) { + mError = error.toString(); + } + + public void setError(String error) { + mError = error; + } + + public void setErrorDescription(String descr) { + if (mErrorDescr == null) + mErrorDescr = new Vector<String>(); + mErrorDescr.addElement(descr); + } + + public void setResult(Object result) { + mResult = result; + mResults.put(RESULT, result); + } + + public void setResult(String name, Object result) { + mResults.put(name, result); + } + + public IArgBlock getHttpParams() { + return mHttpParams; + } + + public HttpServletRequest getHttpReq() { + return mHttpReq; + } + + public HttpServletResponse getHttpResp() { + return mHttpResp; + } + + public ServletConfig getServletConfig() { + return mServletConfig; + } + + public ServletContext getServletContext() { + return mServletContext; + } + + public IRequest getIRequest() { + return mRequest; + } + + public Integer getStatus() { + return mStatus; + } + + public String getError() { + return mError; + } + + public Vector<String> getErrorDescr() { + return mErrorDescr; + } + + public Object getResult() { + return mResult; + } + + public Object getResult(String name) { + return mResults.get(name); + } + + public void setReason(String reason) { + this.reason = reason; + } + + public String getReason() { + return reason; + } + + // handy routines for IRequest. + + public void setExtData(String type, String value) { + if (mRequest != null) { + mRequest.setExtData(type, value); + } + } + + public String getExtData(String type) { + if (mRequest != null) { + return mRequest.getExtDataInString(type); + } else { + return null; + } + } + + // policy errors; set on rejection or possibly deferral. + public Vector<String> getPolicyMessages() { + if (mRequest != null) { + return mRequest.getExtDataInStringVector(IRequest.ERRORS); + } + return null; + } + + /** + * set default CMS status according to IRequest status. + */ + public void setIRequestStatus() throws EBaseException { + if (mRequest == null) { + EBaseException e = + new ECMSGWException(CMS.getLogMessage("CMSGW_MISSING_REQUEST")); + + throw e; + } + + RequestStatus status = mRequest.getRequestStatus(); + + // completed equivalent to success by default. + if (status == RequestStatus.COMPLETE) { + mStatus = CMSRequest.SUCCESS; + return; + } + // unexpected resulting request status. + if (status == RequestStatus.REJECTED) { + mStatus = CMSRequest.REJECTED; + return; + } // pending or service pending. + else if (status == RequestStatus.PENDING) { + mStatus = CMSRequest.PENDING; + return; + } else if (status == RequestStatus.SVC_PENDING) { + mStatus = CMSRequest.SVC_PENDING; + return; + } else { + RequestId reqId = mRequest.getRequestId(); + + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_UNEXPECTED_REQUEST_STATUS_2", + status.toString(), reqId.toString())); + } + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSTemplate.java b/base/common/src/com/netscape/cms/servlet/common/CMSTemplate.java new file mode 100644 index 000000000..317bddbcd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSTemplate.java @@ -0,0 +1,609 @@ +// --- 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.common; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.util.Date; +import java.util.Enumeration; + +import javax.servlet.ServletOutputStream; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; + +/** + * File templates. This implementation will take + * an HTML file with a special customer tag + * <CMS_TEMPLATE> and replace the tag with + * a series of javascript variable definitions + * (depending on the servlet) + * + * @version $Revision$, $Date$ + */ +public class CMSTemplate extends CMSFile { + + public static final String SUFFIX = ".template"; + + /*========================================================== + * variables + *==========================================================*/ + + /* private variables */ + private String mTemplateFileName = ""; + private ILogger mLogger = CMS.getLogger(); + private long mTimeStamp; + + /* public vaiables */ + public String mPreOutput; + public String mPostOutput; + public static final String TEMPLATE_TAG = "<CMS_TEMPLATE>"; + + /* Character set for i18n */ + + /* Will be set by CMSServlet.getTemplate() */ + private String mCharset = null; + + /*========================================================== + * constructors + *==========================================================*/ + + /** + * Constructor + * + * @param file template file to load + * @param charset character set + * @throws IOException if the there was an error opening the file + */ + public CMSTemplate(File file, String charset) throws IOException, EBaseException { + mCharset = charset; + mAbsPath = file.getAbsolutePath(); + mLastModified = file.lastModified(); + try { + init(file); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_CANT_LOAD_TEMPLATE", mAbsPath, e.toString())); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_LOADING_TEMPLATE")); + } + String content = mPreOutput + mPostOutput; + + mContent = content.getBytes(mCharset); + } + + /*========================================================== + * public methods + *==========================================================*/ + + /* * + * Load the form from the file and setup the + * pre/post output buffer if it is a template + * file. Otherwise, only post output buffer is + * filled. + * @param template the template file to load + * @return true if successful + */ + public boolean init(File template) throws EBaseException, IOException { + /* load template */ + String content = loadFile(template); + + if (content == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_TEMPLATE_EMPTY", mAbsPath)); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_TEMPLATE_NO_CONTENT_1", mAbsPath)); + } + + /* time stamp */ + Date now = CMS.getCurrentDate(); + + mTimeStamp = now.getTime(); + + /* if template file, find template tag substring and set + * pre/post output string + */ + int location = content.indexOf(TEMPLATE_TAG); + + if (location == -1) { + log(ILogger.LL_FAILURE, CMS.getLogMessage( + "CMSGW_TEMPLATE_MISSING", mAbsPath, TEMPLATE_TAG)); + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_MISSING_TEMPLATE_TAG_2", + TEMPLATE_TAG, mAbsPath)); + } + mPreOutput = content.substring(0, location); + mPostOutput = content.substring(TEMPLATE_TAG.length() + location); + + return true; + } + + /** + * Write a javascript representation of 'input' + * surrounded by SCRIPT tags to the outputstream + * + * @param rout the outputstream to write to + * @param input the parameters to write + */ + public void renderOutput(OutputStream rout, CMSTemplateParams input) + throws IOException { + Enumeration<String> e = null; + Enumeration<IArgBlock> q = null; + IArgBlock r = null; + CMSTemplateParams data = (CMSTemplateParams) input; + HTTPOutputStreamWriter http_out = null; + + if (mCharset == null) + http_out = new HTTPOutputStreamWriter(rout); + else + http_out = new HTTPOutputStreamWriter(rout, mCharset); + + try { + templateLine out = new templateLine(); + + // Output the prolog + out.print(mPreOutput); + + // Output the header data + out.println("<SCRIPT LANGUAGE=\"JavaScript\">"); + out.println("var header = new Object();"); + out.println("var fixed = new Object();"); + out.println("var recordSet = new Array;"); + out.println("var result = new Object();"); + + // hack + out.println("var httpParamsCount = 0;"); + out.println("var httpHeadersCount = 0;"); + out.println("var authTokenCount = 0;"); + out.println("var serverAttrsCount = 0;"); + out.println("header.HTTP_PARAMS = new Array;"); + out.println("header.HTTP_HEADERS = new Array;"); + out.println("header.AUTH_TOKEN = new Array;"); + out.println("header.SERVER_ATTRS = new Array;"); + + r = data.getHeader(); + if (r != null) { + e = r.elements(); + while (e.hasMoreElements()) { + String n = e.nextElement(); + Object v = r.getValue(n); + + out.println("header." + n + " = " + renderValue(v) + ";"); + } + } + + // Output the fixed data + r = data.getFixed(); + if (r != null) { + e = r.elements(); + while (e.hasMoreElements()) { + String n = e.nextElement(); + Object v = r.getValue(n); + + out.println("fixed." + n + " = " + renderValue(v) + ";"); + } + } + + // Output the query data + q = data.queryRecords(); + if (q != null && q.hasMoreElements()) { + out.println("var recordCount = 0;"); + out.println("var record;"); + while (q.hasMoreElements()) { + out.println("record = new Object;"); + out.println("record.HTTP_PARAMS = new Array;"); + out.println("record.HTTP_HEADERS = new Array;"); + out.println("record.AUTH_TOKEN = new Array;"); + out.println("record.SERVER_ATTRS = new Array;"); + + // Get a query record + r = q.nextElement(); + e = r.elements(); + while (e.hasMoreElements()) { + String n = e.nextElement(); + Object v = r.getValue(n); + + out.println("record." + n + "=" + renderValue(v) + ";"); + } + out.println("recordSet[recordCount++] = record;"); + } + out.println("record.recordSet = recordSet;"); + } + + //if (headerBlock) + out.println("result.header = header;"); + //if (fixedBlock) + out.println("result.fixed = fixed;"); + //if (queryBlock) + out.println("result.recordSet = recordSet;"); + out.println("</SCRIPT>"); + out.println(mPostOutput); + http_out.print(out.toString()); + + } catch (EBaseException ex) { + throw new IOException(ex.getMessage()); + } + } + + /** + * Ouput the pre-amble HTML Header including + * the pre-output buffer. + * + * @param out output stream specified + * @return success or error + */ + public boolean outputProlog(PrintWriter out) { + + //Debug.trace("FormCache:outputProlog"); + + /* output pre-output buffer */ + out.print(mPreOutput); + + /* output JavaScript variables and objects */ + out.println("<SCRIPT LANGUAGE=\"JavaScript\">"); + out.println("var header = new Object();"); + out.println("var result = new Object();"); + + return true; + } + + /** + * Output the post HTML tags and post-output + * buffer. + * + * @param out output stream specified + * @return success or error + */ + public boolean outputEpilog(PrintWriter out) { + + out.println("</SCRIPT>"); + out.println(mPostOutput); + + return true; + } + + /** + * @return full path of template + */ + public String getTemplateName() { + return mAbsPath; + } + + // inherit getabspath, getContent, get last access and set last access + + /*========================================================== + * private methods + *==========================================================*/ + + /* load file into string */ + private String loadFile(File template) throws IOException { + + // Debug.trace("FormCache:loadFile"); + + /* create input stream, can throw IOException */ + FileInputStream inStream = new FileInputStream(template); + InputStreamReader inReader = new InputStreamReader(inStream, mCharset); + ; + BufferedReader in = new BufferedReader(inReader); + StringBuffer buf = new StringBuffer(); + String line; + + while ((line = in.readLine()) != null) { + buf.append(line); + buf.append('\n'); + } + try { + in.close(); + inStream.close(); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERR_CLOSE_TEMPL_FILE", mAbsPath, e.getMessage())); + } + return buf.toString(); + } + + private String renderValue(Object v) { + String s = null; + + // Figure out the type of object + if (v instanceof IRawJS) { + s = v.toString(); + } else if (v instanceof String) { + if (v.equals("")) + s = "null"; + else + s = "\"" + escapeJavaScriptString((String) v) + "\""; + } else if (v instanceof Integer) { + s = ((Integer) v).toString(); + } else if (v instanceof Boolean) { + + if (((Boolean) v).booleanValue() == true) { + s = "true"; + } else { + s = "false"; + } + } else if (v instanceof BigInteger) { + s = ((BigInteger) v).toString(10); + } else if (v instanceof Character && + ((Character) v).equals(Character.valueOf((char) 0))) { + s = "null"; + } else { + s = "\"" + v.toString() + "\""; + } + + return s; + } + + /** + * Escape the contents of src string in preparation to be enclosed in + * double quotes as a JavaScript String Literal within an <script> + * portion of an HTML document. + * stevep - performance improvements - about 4 times faster than before. + */ + public static 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]; + + if ((c > 0x23) && (c != 0x5c) && (c != 0x3c) && (c != 0x3e)) { + out[j++] = c; + continue; + } + + if ((c == 0x5c) && ((i + 1) < l) && (in[i + 1] == 'n' || + in[i + 1] == 'r' || in[i + 1] == 'f' || in[i + 1] == 't' || + in[i + 1] == '<' || in[i + 1] == '>' || + in[i + 1] == '\"' || in[i + 1] == '\'' || in[i + 1] == '\\')) { + if (in[i + 1] == 'x' && ((i + 3) < l) && in[i + 2] == '3' && + (in[i + 3] == 'c' || in[i + 3] == 'e')) { + out[j++] = '\\'; + out[j++] = in[i + 1]; + out[j++] = in[i + 2]; + out[j++] = in[i + 3]; + i += 3; + } else { + out[j++] = '\\'; + out[j++] = in[i + 1]; + i++; + } + continue; + } + + switch (c) { + case '\n': + out[j++] = '\\'; + out[j++] = 'n'; + break; + + case '\\': + out[j++] = '\\'; + out[j++] = '\\'; + break; + + case '\"': + out[j++] = '\\'; + out[j++] = '\"'; + break; + + case '\r': + out[j++] = '\\'; + out[j++] = 'r'; + break; + + case '\f': + out[j++] = '\\'; + out[j++] = 'f'; + break; + + case '\t': + out[j++] = '\\'; + out[j++] = 't'; + break; + + case '<': + out[j++] = '\\'; + out[j++] = 'x'; + out[j++] = '3'; + out[j++] = 'c'; + break; + + case '>': + out[j++] = '\\'; + out[j++] = 'x'; + out[j++] = '3'; + out[j++] = 'e'; + break; + + default: + out[j++] = c; + } + } + return new String(out, 0, j); + } + + /** + * Like escapeJavaScriptString(String s) but also escape '[' for + * HTML processing. + */ + public static String escapeJavaScriptStringHTML(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]; + + if (c > 0x5C) { + out[j++] = c; + continue; + } + + if ((c == 0x5c) && ((i + 1) < l) && (in[i + 1] == 'n' || + in[i + 1] == 'r' || in[i + 1] == 'f' || in[i + 1] == 't' || + in[i + 1] == '<' || in[i + 1] == '>' || + in[i + 1] == '\"' || in[i + 1] == '\'' || in[i + 1] == '\\')) { + if (in[i + 1] == 'x' && ((i + 3) < l) && in[i + 2] == '3' && + (in[i + 3] == 'c' || in[i + 3] == 'e')) { + out[j++] = '\\'; + out[j++] = in[i + 1]; + out[j++] = in[i + 2]; + out[j++] = in[i + 3]; + i += 3; + } else { + out[j++] = '\\'; + out[j++] = in[i + 1]; + i++; + } + continue; + } + + switch (c) { + case '\n': + out[j++] = '\\'; + out[j++] = 'n'; + break; + + case '\\': + out[j++] = '\\'; + out[j++] = '\\'; + break; + + case '\"': + out[j++] = '\\'; + out[j++] = '\"'; + break; + + case '\r': + out[j++] = '\\'; + out[j++] = 'r'; + break; + + case '\f': + out[j++] = '\\'; + out[j++] = 'f'; + break; + + case '\t': + out[j++] = '\\'; + out[j++] = 't'; + break; + + case '<': + out[j++] = '\\'; + out[j++] = 'x'; + out[j++] = '3'; + out[j++] = 'c'; + break; + case '>': + out[j++] = '\\'; + out[j++] = 'x'; + out[j++] = '3'; + out[j++] = 'e'; + break; + + default: + out[j++] = c; + } + } + return new String(out, 0, j); + } + + /** + * for debugging, return contents that would've been outputed. + */ + public String getOutput(CMSTemplateParams input) + throws IOException { + debugOutputStream out = new debugOutputStream(); + + renderOutput(out, input); + return out.toString(); + } + + private class HTTPOutputStreamWriter extends OutputStreamWriter { + public HTTPOutputStreamWriter(OutputStream out) + throws UnsupportedEncodingException { + super(out); + } + + public HTTPOutputStreamWriter(OutputStream out, String enc) + throws UnsupportedEncodingException { + super(out, enc); + } + + public void print(String s) throws IOException { + write(s, 0, s.length()); + flush(); + return; + } + } + + private class templateLine { + private StringBuffer s = new StringBuffer(); + + void println(String p) { + s.append('\n'); + s.append(p); + } + + void print(String p) { + s.append(p); + } + + public String toString() { + return s.toString(); + } + + } + + private static class debugOutputStream extends ServletOutputStream { + private StringWriter mStringWriter = new StringWriter(); + + public debugOutputStream() { + super(); + } + + public void write(int b) throws IOException { + mStringWriter.write(b); + } + + public String toString() { + return mStringWriter.toString(); + } + + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/common/CMSTemplateParams.java b/base/common/src/com/netscape/cms/servlet/common/CMSTemplateParams.java new file mode 100644 index 000000000..ce2c26c3c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/CMSTemplateParams.java @@ -0,0 +1,70 @@ +// --- 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.common; + +import java.util.Enumeration; +import java.util.Vector; + +import com.netscape.certsrv.base.IArgBlock; + +/** + * Holds template parameters + * + * @version $Revision$, $Date$ + */ +public class CMSTemplateParams { + private IArgBlock mHeader = null; + private IArgBlock mFixed = null; + private Vector<IArgBlock> mRepeat = new Vector<IArgBlock>(); + + public CMSTemplateParams() { + } + + public CMSTemplateParams(IArgBlock header, IArgBlock fixed) { + mHeader = header; + mFixed = fixed; + } + + public void setHeader(IArgBlock h) { + mHeader = h; + } + + public IArgBlock getHeader() { + return mHeader; + } + + public void setFixed(IArgBlock f) { + mFixed = f; + } + + public IArgBlock getFixed() { + return mFixed; + } + + public void addRepeatRecord(IArgBlock r) { + mRepeat.addElement(r); + } + + public void clearRepeatRecords() { + mRepeat = new Vector<IArgBlock>(); + } + + public Enumeration<IArgBlock> queryRecords() { + return mRepeat.elements(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/ECMSGWException.java b/base/common/src/com/netscape/cms/servlet/common/ECMSGWException.java new file mode 100644 index 000000000..e8b848f7d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/ECMSGWException.java @@ -0,0 +1,74 @@ +// --- 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.common; + +import com.netscape.certsrv.base.EBaseException; + +/** + * A class represents a CMS gateway exception. + * <P> + * + * @version $Revision$, $Date$ + */ +public class ECMSGWException extends EBaseException { + + /** + * + */ + private static final long serialVersionUID = 7546430025179838019L; + /** + * CA resource class name. + */ + private static final String CMSGW_RESOURCES = CMSGWResources.class.getName(); + + /** + * Constructs a CMS Gateway exception. + * <P> + */ + public ECMSGWException(String msgFormat) { + super(msgFormat); + } + + /** + * Constructs a CMSGW exception. + * <P> + */ + public ECMSGWException(String msgFormat, String param) { + super(msgFormat, param); + } + + /** + * Constructs a CMSGW exception. + * <P> + */ + public ECMSGWException(String msgFormat, Exception e) { + super(msgFormat, e); + } + + /** + * Constructs a CMSGW exception. + * <P> + */ + public ECMSGWException(String msgFormat, Object params[]) { + super(msgFormat, params); + } + + protected String getBundleName() { + return CMSGW_RESOURCES; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java new file mode 100644 index 000000000..40edb3bda --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java @@ -0,0 +1,102 @@ +// --- 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.common; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; + +/** + * Default error template filler + * + * @version $Revision$, $Date$ + */ +public class GenErrorTemplateFiller implements ICMSTemplateFiller { + public GenErrorTemplateFiller() { + } + + /** + * fill error details and description if any. + * + * @param cmsReq the CMS Request. + * @param authority the authority + * @param locale the locale of template. + * @param e unexpected error. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + // request status if any. + if (cmsReq != null) { + Integer sts = cmsReq.getStatus(); + + if (sts != null) + fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString()); + } else { + CMS.debug("GenErrorTemplateFiller::getTemplateParams() - " + + "cmsReq is null!"); + return null; + } + + // error + String ex = cmsReq.getError(); + + // Changed by beomsuk + /*if (ex == null) + ex = new EBaseException(CMS.getLogMessage("BASE_UNKNOWN_ERROR")); + fixed.set(ICMSTemplateFiller.ERROR, ex.toString(locale)); + */ + if ((ex == null) && (cmsReq.getReason() == null)) + ex = new EBaseException(CMS.getLogMessage("BASE_UNKNOWN_ERROR")).toString(); + else if (ex != null) + fixed.set(ICMSTemplateFiller.ERROR, ex); + else if (cmsReq.getReason() != null) + fixed.set(ICMSTemplateFiller.ERROR, cmsReq.getReason()); + // Change end + + // error description if any. + Vector<String> descr = cmsReq.getErrorDescr(); + + if (descr != null) { + Enumeration<String> num = descr.elements(); + + while (num.hasMoreElements()) { + String elem = num.nextElement(); + //System.out.println("Setting description "+elem.toString()); + IArgBlock argBlock = CMS.createArgBlock(); + + argBlock.set(ICMSTemplateFiller.ERROR_DESCR, + elem); + params.addRepeatRecord(argBlock); + } + } + + // this authority + if (authority != null) + fixed.set(ICMSTemplateFiller.AUTHORITY, + authority.getOfficialName()); + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java new file mode 100644 index 000000000..1d479fef3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java @@ -0,0 +1,287 @@ +// --- 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.common; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.OutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Date; +import java.util.Locale; + +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.pkix.cmc.CMCStatusInfo; +import org.mozilla.jss.pkix.cmc.OtherInfo; +import org.mozilla.jss.pkix.cmc.PendInfo; +import org.mozilla.jss.pkix.cmc.ResponseBody; +import org.mozilla.jss.pkix.cmc.TaggedAttribute; +import org.mozilla.jss.pkix.cms.ContentInfo; +import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo; +import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber; +import org.mozilla.jss.pkix.cms.SignedData; +import org.mozilla.jss.pkix.cms.SignerIdentifier; +import org.mozilla.jss.pkix.cms.SignerInfo; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.Name; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; + +/** + * default Pending template filler + * + * @version $Revision$, $Date$ + */ +public class GenPendingTemplateFiller implements ICMSTemplateFiller { + public static String FULL_RESPONSE = "cmcFullEnrollmentResponse"; + + public GenPendingTemplateFiller() { + } + + /** + * fill error details and description if any. + * + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + if (cmsReq == null) { + return null; + } + + // request status if any. + Integer sts = cmsReq.getStatus(); + + if (sts != null) + fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString()); + + // request id + IRequest req = cmsReq.getIRequest(); + + if (req != null) { + RequestId reqId = req.getRequestId(); + + fixed.set(ICMSTemplateFiller.REQUEST_ID, reqId); + // set pendInfo, CMCStatusInfo + IArgBlock httpParams = cmsReq.getHttpParams(); + + if (doFullResponse(httpParams)) { + SEQUENCE controlSeq = new SEQUENCE(); + int bpid = 1; + PendInfo pendInfo = new PendInfo(reqId.toString(), new + Date()); + OtherInfo otherInfo = new + OtherInfo(OtherInfo.PEND, null, pendInfo); + SEQUENCE bpids = new SEQUENCE(); + String[] reqIdArray = + req.getExtDataInStringArray(IRequest.CMC_REQIDS); + + for (int i = 0; i < reqIdArray.length; i++) { + bpids.addElement(new INTEGER(reqIdArray[i])); + } + CMCStatusInfo cmcStatusInfo = new + CMCStatusInfo(CMCStatusInfo.PENDING, bpids, + (String) null, otherInfo); + TaggedAttribute ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, + cmcStatusInfo); + + controlSeq.addElement(ta); + // copy transactionID, senderNonce, + // create recipientNonce + // create responseInfo if regInfo exist + String[] transIds = + req.getExtDataInStringArray(IRequest.CMC_TRANSID); + SET ids = new SET(); + + for (int i = 0; i < transIds.length; i++) { + ids.addElement(new INTEGER(transIds[i])); + } + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_transactionId, + ids); + controlSeq.addElement(ta); + + String[] senderNonce = req.getExtDataInStringArray(IRequest.CMC_SENDERNONCE); + SET nonces = new SET(); + + for (int i = 0; i < senderNonce.length; i++) { + nonces.addElement(new OCTET_STRING(senderNonce[i].getBytes())); + } + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_recipientNonce, + nonces); + controlSeq.addElement(ta); + req.setExtData(IRequest.CMC_RECIPIENTNONCE, senderNonce); + + Date date = CMS.getCurrentDate(); + String salt = "lala123" + date.toString(); + byte[] dig; + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + + dig = SHA1Digest.digest(salt.getBytes()); + } catch (NoSuchAlgorithmException ex) { + dig = salt.getBytes(); + } + String b64E = CMS.BtoA(dig); + String[] newNonce = { b64E }; + + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_senderNonce, + new OCTET_STRING(newNonce[0].getBytes())); + controlSeq.addElement(ta); + req.setExtData(IRequest.CMC_SENDERNONCE, newNonce); + + ResponseBody rb = new ResponseBody(controlSeq, new + SEQUENCE(), new + SEQUENCE()); + EncapsulatedContentInfo ci = new + EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIResponse, + rb); + org.mozilla.jss.crypto.X509Certificate x509cert = null; + + if (authority instanceof ICertificateAuthority) { + x509cert = ((ICertificateAuthority) authority).getCaX509Cert(); + } else if (authority instanceof IRegistrationAuthority) { + x509cert = ((IRegistrationAuthority) authority).getRACert(); + } + if (x509cert == null) + return params; + try { + X509CertImpl cert = new X509CertImpl(x509cert.getEncoded()); + ByteArrayInputStream issuer1 = new + ByteArrayInputStream(((X500Name) cert.getIssuerDN()).getEncoded()); + Name issuer = (Name) Name.getTemplate().decode(issuer1); + IssuerAndSerialNumber ias = new + IssuerAndSerialNumber(issuer, new INTEGER(cert.getSerialNumber().toString())); + SignerIdentifier si = new + SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null); + + // SHA1 is the default digest Alg for now. + DigestAlgorithm digestAlg = null; + SignatureAlgorithm signAlg = null; + org.mozilla.jss.crypto.PrivateKey privKey = CryptoManager.getInstance().findPrivKeyByCert(x509cert); + org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType(); + + if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.RSA)) { + signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest; + } else if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.DSA)) { + signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest; + } else { + CMS.debug("GenPendingTemplateFiller::getTemplateParams() - " + + "keyType " + keyType.toString() + + " is unsupported!"); + return null; + } + + MessageDigest SHADigest = null; + byte[] digest = null; + + try { + SHADigest = MessageDigest.getInstance("SHA1"); + digestAlg = DigestAlgorithm.SHA1; + + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + rb.encode((OutputStream) ostream); + digest = SHADigest.digest(ostream.toByteArray()); + } catch (NoSuchAlgorithmException ex) { + //log("digest fail"); + } + + SignerInfo signInfo = new + SignerInfo(si, null, null, + OBJECT_IDENTIFIER.id_cct_PKIResponse, + digest, signAlg, + privKey); + SET signInfos = new SET(); + + signInfos.addElement(signInfo); + + SET digestAlgs = new SET(); + + if (digestAlg != null) { + AlgorithmIdentifier ai = new + AlgorithmIdentifier(digestAlg.toOID(), + null); + + digestAlgs.addElement(ai); + } + + SignedData fResponse = new + SignedData(digestAlgs, ci, + null, null, signInfos); + ContentInfo fullResponse = new + ContentInfo(ContentInfo.SIGNED_DATA, fResponse); + ByteArrayOutputStream ostream = new + ByteArrayOutputStream(); + + fullResponse.encode((OutputStream) ostream); + byte[] fr = ostream.toByteArray(); + + fixed.set(FULL_RESPONSE, CMS.BtoA(fr)); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + } + // this authority + if (authority != null) + fixed.set(ICMSTemplateFiller.AUTHORITY, + authority.getOfficialName()); + return params; + } + + /** + * handy routine to check if client want full enrollment response + */ + public static boolean doFullResponse(IArgBlock httpParams) { + if (httpParams.getValueAsBoolean("fullResponse", false)) + return true; + else + return false; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java new file mode 100644 index 000000000..9e75cc799 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java @@ -0,0 +1,92 @@ +// --- 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.common; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; + +/** + * default Service Pending template filler + * + * @version $Revision$, $Date$ + */ +public class GenRejectedTemplateFiller implements ICMSTemplateFiller { + public final static String POLICY_MESSAGE = "policyMessage"; + + public GenRejectedTemplateFiller() { + } + + /** + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + // request status if any. + if (cmsReq != null) { + Integer sts = cmsReq.getStatus(); + + if (sts != null) + fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString()); + } else { + CMS.debug("GenRejectedTemplateFiller::getTemplateParams() - " + + "cmsReq is null!"); + return null; + } + + // request id + IRequest req = cmsReq.getIRequest(); + + if (req != null) { + fixed.set(ICMSTemplateFiller.REQUEST_ID, req.getRequestId()); + + // policy errors (rejection reasons) + Vector<String> messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration<String> msgs = messages.elements(); + + while (msgs.hasMoreElements()) { + String ex = msgs.nextElement(); + IArgBlock messageArgBlock = CMS.createArgBlock(); + + messageArgBlock.set(POLICY_MESSAGE, ex); + params.addRepeatRecord(messageArgBlock); + } + } + } + + // this authority + + if (authority != null) + fixed.set(ICMSTemplateFiller.AUTHORITY, + authority.getOfficialName()); + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java new file mode 100644 index 000000000..f6de38412 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java @@ -0,0 +1,63 @@ +// --- 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.common; + +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.IArgBlock; + +/** + * default Success template filler + * + * @version $Revision$, $Date$ + */ +public class GenSuccessTemplateFiller implements ICMSTemplateFiller { + + public GenSuccessTemplateFiller() { + } + + /** + * fill error details and description if any. + * + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + // request status if any. + if (cmsReq != null) { + Integer sts = cmsReq.getStatus(); + + if (sts != null) + fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString()); + } + + // this authority + if (authority != null) + fixed.set(ICMSTemplateFiller.AUTHORITY, + authority.getOfficialName()); + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java new file mode 100644 index 000000000..ec1b97779 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java @@ -0,0 +1,79 @@ +// --- 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.common; + +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; + +/** + * default Service Pending template filler + * + * @version $Revision$, $Date$ + */ +public class GenSvcPendingTemplateFiller implements ICMSTemplateFiller { + public static final String REMOTE_AUTHORITY = "remoteAuthority"; + + public GenSvcPendingTemplateFiller() { + } + + /** + * fill error details and description if any. + * + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + // request status if any. + if (cmsReq != null) { + Integer sts = cmsReq.getStatus(); + + if (sts != null) + fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString()); + + // request id + IRequest req = cmsReq.getIRequest(); + + if (req != null) { + fixed.set(ICMSTemplateFiller.REQUEST_ID, req.getRequestId()); + + // remote authority we're waiting for + String remoteAuthority = + req.getExtDataInString(IRequest.REMOTE_SERVICE_AUTHORITY); + + if (remoteAuthority != null) + fixed.set(REMOTE_AUTHORITY, remoteAuthority); + } + } + + // this authority + if (authority != null) + fixed.set(ICMSTemplateFiller.AUTHORITY, + authority.getOfficialName()); + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java new file mode 100644 index 000000000..cab1b36e6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java @@ -0,0 +1,67 @@ +// --- 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.common; + +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.IArgBlock; + +/** + * default Unauthorized template filler + * + * @version $Revision$, $Date$ + */ +public class GenUnauthorizedTemplateFiller implements ICMSTemplateFiller { + + public GenUnauthorizedTemplateFiller() { + } + + /** + * fill error details and description if any. + * + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + // request status if any. + if (cmsReq != null) { + Integer sts = cmsReq.getStatus(); + + if (sts != null) + fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString()); + } + + // set unauthorized error + fixed.set(ICMSTemplateFiller.ERROR, + new ECMSGWException(CMS.getLogMessage("CMSGW_UNAUTHORIZED"))); + + // this authority + if (authority != null) + fixed.set(ICMSTemplateFiller.AUTHORITY, + authority.getOfficialName()); + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java new file mode 100644 index 000000000..8b560d7bc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java @@ -0,0 +1,76 @@ +// --- 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.common; + +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; + +/** + * default unexpected error template filler + * + * @version $Revision$, $Date$ + */ +public class GenUnexpectedErrorTemplateFiller implements ICMSTemplateFiller { + + public GenUnexpectedErrorTemplateFiller() { + } + + /** + * fill error details and description if any. + * + * @param cmsReq CMS Request + * @param authority this authority + * @param locale locale of template. + * @param e unexpected exception e. ignored. + */ + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) { + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(null, fixed); + + // When an exception occurs the exit is non-local which probably + // will leave the requestStatus value set to something other + // than CMSRequest.EXCEPTION, so force the requestStatus to + // EXCEPTION since it must be that if we're here. + Integer sts = CMSRequest.EXCEPTION; + if (cmsReq != null) + cmsReq.setStatus(sts); + fixed.set(ICMSTemplateFiller.REQUEST_STATUS, sts.toString()); + + // the unexpected error (exception) + if (e == null) + e = new EBaseException(CMS.getLogMessage("BASE_UNKNOWN_ERROR")); + String errMsg = null; + + if (e instanceof EBaseException) + errMsg = ((EBaseException) e).toString(locale); + else + errMsg = e.toString(); + fixed.set(ICMSTemplateFiller.EXCEPTION, errMsg); + + // this authority + if (authority != null) + fixed.set(ICMSTemplateFiller.AUTHORITY, + authority.getOfficialName()); + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java new file mode 100644 index 000000000..2d046f0ee --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java @@ -0,0 +1,49 @@ +// --- 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.common; + +import java.util.Locale; + +import com.netscape.certsrv.authority.IAuthority; + +/** + * This interface represents a template filler. + * + * @version $Revision$, $Date$ + */ +public interface ICMSTemplateFiller { + // common template variables. + public final static String ERROR = "errorDetails"; + public final static String ERROR_DESCR = "errorDescription"; + public final static String EXCEPTION = "unexpectedError"; + + public static final String HOST = "host"; + public static final String PORT = "port"; + public static final String SCHEME = "scheme"; + + public static final String AUTHORITY = "authorityName"; + + public static final String REQUEST_STATUS = "requestStatus"; + + public static final String KEYREC_ID = "keyrecId"; + public static final String REQUEST_ID = "requestId"; + + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority mAuthority, Locale locale, Exception e) + throws Exception; +} diff --git a/base/common/src/com/netscape/cms/servlet/common/IRawJS.java b/base/common/src/com/netscape/cms/servlet/common/IRawJS.java new file mode 100644 index 000000000..827f24f1d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/IRawJS.java @@ -0,0 +1,26 @@ +// --- 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.common; + +/** + * This represents raw JS parameters. + * + * @version $Revision$, $Date$ + */ +public interface IRawJS { +} diff --git a/base/common/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java b/base/common/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java new file mode 100644 index 000000000..59c4a0fe4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java @@ -0,0 +1,114 @@ +// --- 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.common; + +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.ISubsystem; + +/** + * A class represents a certificate server kernel. This + * kernel contains a list of resident subsystems such + * as logging, security, remote administration. Additional + * subsystems can be loaded into this kernel by specifying + * parameters in the configuration store. + * <P> + * + * @version $Revision$, $Date$ + */ +public class IndexTemplateFiller implements ICMSTemplateFiller { + + private final static String INFO = "index"; + + // input parameters + + // output parameters + private final static String OUT_TYPE = "type"; + private final static String OUT_ID = "id"; + private final static String OUT_TOTAL_COUNT = "totalCount"; + private final static String OUT_ERROR = "errorDetails"; + + public IndexTemplateFiller() { + } + + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority mAuthority, Locale locale, Exception e) { + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams params = new CMSTemplateParams(header, ctx); + + ISubsystem ca = CMS.getSubsystem("ca"); + ISubsystem ra = CMS.getSubsystem("ra"); + ISubsystem kra = CMS.getSubsystem("kra"); + ISubsystem ocsp = CMS.getSubsystem("ocsp"); + ISubsystem tks = CMS.getSubsystem("tks"); + + IArgBlock rarg = null; + int count = 0; + + if (ca != null) { + rarg = CMS.createArgBlock(); + rarg.addStringValue(OUT_TYPE, "CertificateAuthority"); + rarg.addStringValue(OUT_ID, "ca"); + params.addRepeatRecord(rarg); + count++; + } + if (ra != null) { + rarg = CMS.createArgBlock(); + rarg.addStringValue(OUT_TYPE, "RegistrationAuthority"); + rarg.addStringValue(OUT_ID, "ra"); + params.addRepeatRecord(rarg); + count++; + } + if (ocsp != null) { + rarg = CMS.createArgBlock(); + rarg.addStringValue(OUT_TYPE, "OCSPAuthority"); + rarg.addStringValue(OUT_ID, "ocsp"); + params.addRepeatRecord(rarg); + count++; + } + if (kra != null) { + rarg = CMS.createArgBlock(); + rarg.addStringValue(OUT_TYPE, "KeyRecoveryAuthority"); + rarg.addStringValue(OUT_ID, "kra"); + params.addRepeatRecord(rarg); + count++; + } + if (tks != null) { + rarg = CMS.createArgBlock(); + rarg.addStringValue(OUT_TYPE, "TKSAuthority"); + rarg.addStringValue(OUT_ID, "tks"); + params.addRepeatRecord(rarg); + count++; + } + // information about what is selected is provided + // from the caller. This parameter (selected) is used + // by header servlet + try { + header.addStringValue("selected", + cmsReq.getHttpParams().getValueAsString("selected")); + } catch (EBaseException ex) { + } + header.addIntegerValue(OUT_TOTAL_COUNT, count); + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/RawJS.java b/base/common/src/com/netscape/cms/servlet/common/RawJS.java new file mode 100644 index 000000000..f936e0757 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/RawJS.java @@ -0,0 +1,35 @@ +// --- 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.common; + +/** + * This represents raw JS parameters. + * + * @version $Revision$, $Date$ + */ +public class RawJS implements IRawJS { + private String mRawJSstr = null; + + public RawJS(String s) { + mRawJSstr = s; + } + + public String toString() { + return mRawJSstr; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/common/ServletUtils.java b/base/common/src/com/netscape/cms/servlet/common/ServletUtils.java new file mode 100644 index 000000000..5c16b8195 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/common/ServletUtils.java @@ -0,0 +1,106 @@ +// --- 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.common; + +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; + +/** + * Utility class + * + * @version $Revision$, $Date$ + */ +public class ServletUtils { + + 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"; + + public static String initializeAuthz(ServletConfig sc, + IAuthzSubsystem authz, String id) throws ServletException { + String srcType = AUTHZ_SRC_LDAP; + + try { + IConfigStore authzConfig = + CMS.getConfigStore().getSubStore(AUTHZ_CONFIG_STORE); + + srcType = authzConfig.getString(AUTHZ_SRC_TYPE, AUTHZ_SRC_LDAP); + } catch (EBaseException e) { + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_FAIL_SRC_TYPE")); + } + + String aclMethod = null; + + if (srcType.equalsIgnoreCase(AUTHZ_SRC_XML)) { + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_INITED", "")); + aclMethod = sc.getInitParameter(PROP_AUTHZ_MGR); + if (aclMethod != null && + aclMethod.equalsIgnoreCase(AUTHZ_MGR_BASIC)) { + String aclInfo = sc.getInitParameter(PROP_ACL); + + if (aclInfo != null) { + try { + addACLInfo(authz, aclMethod, aclInfo); + } catch (EBaseException ee) { + throw new ServletException( + "failed to init authz info from xml config file"); + } + + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTHZ_MGR_INIT_DONE", + id)); + } else { + CMS.debug(CMS.getLogMessage( + "ADMIN_SRVLT_PROP_ACL_NOT_SPEC", PROP_ACL, id, + AUTHZ_MGR_LDAP)); + } + } else { + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_PROP_ACL_NOT_SPEC", + PROP_AUTHZ_MGR, id, AUTHZ_MGR_LDAP)); + } + } else { + aclMethod = AUTHZ_MGR_LDAP; + CMS.debug(CMS.getLogMessage("ADMIN_SRVLT_AUTH_LDAP_NOT_XML", id)); + } + + return aclMethod; + } + + public static void addACLInfo(IAuthzSubsystem authz, String aclMethod, + String aclInfo) throws EBaseException { + + StringTokenizer tokenizer = new StringTokenizer(aclInfo, "#"); + + while (tokenizer.hasMoreTokens()) { + String acl = (String) tokenizer.nextToken(); + + authz.authzMgrAccessInit(aclMethod, acl); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/connector/CloneServlet.java b/base/common/src/com/netscape/cms/servlet/connector/CloneServlet.java new file mode 100644 index 000000000..f9085a5bc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/connector/CloneServlet.java @@ -0,0 +1,579 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.connector; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthCredentials; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.EInvalidCredentials; +import com.netscape.certsrv.authentication.IAuthManager; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.connector.IPKIMessage; +import com.netscape.certsrv.connector.IRequestEncoder; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; + +/** + * Clone servlet - part of the Clone Authority (CLA) + * processes Revoked certs from its dependant clone CAs + * service request and return status. + * + * @version $Revision$, $Date$ + */ +public class CloneServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -3474557834182380981L; + public static final String INFO = "Clone Servlet"; + public final static String PROP_AUTHORITY = "authority"; + protected ServletConfig mConfig = null; + protected IAuthority mAuthority = null; + protected IRequestEncoder mReqEncoder = null; + protected IAuthSubsystem mAuthSubsystem = null; + protected ILogger mLogger = CMS.getLogger(); + + public CloneServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mConfig = sc; + String authority = sc.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) + CMS.getSubsystem(authority); + mReqEncoder = CMS.getHttpRequestEncoder(); + mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + } + + public void service(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, IOException { + boolean running_state = CMS.isInRunningState(); + + if (!running_state) + throw new IOException( + "CMS server is not ready to serve."); + + CMSRequest cmsRequest = newCMSRequest(); + + // set argblock + cmsRequest.setHttpParams(CMS.createArgBlock(toHashtable(req))); + + // set http request + cmsRequest.setHttpReq(req); + + // set http response + cmsRequest.setHttpResp(resp); + + // set servlet config. + cmsRequest.setServletConfig(mConfig); + + // set servlet context. + cmsRequest.setServletContext(mConfig.getServletContext()); + + char[] content = null; + String encodedreq = null; + String method = null; + int len = -1; + IPKIMessage msg = null; + IPKIMessage replymsg = null; + + // NOTE must read all bufer before redoing handshake for + // ssl client auth for client auth to work. + + // get request method + method = req.getMethod(); + + // get content length + len = req.getContentLength(); + + // get content, a base 64 encoded serialized request. + if (len > 0) { + InputStream in = req.getInputStream(); + InputStreamReader inreader = new InputStreamReader(in, "UTF8"); + BufferedReader reader = new BufferedReader(inreader, len); + + content = new char[len]; + int done = reader.read(content, 0, len); + int total = done; + + while (done >= 0 && total < len) { + done = reader.read(content, total, len - total); + total += done; + } + reader.close(); + encodedreq = new String(content); + } + + // force client auth handshake, validate clone CA (CCA) + // and get CCA's Id. + // NOTE must do this after all contents are read for ssl + // redohandshake to work + + X509Certificate peerCert; + + try { + peerCert = getPeerCert(req); + } catch (EBaseException e) { + mAuthority.log(ILogger.LL_SECURITY, + CMS.getLogMessage("CMSGW_HAS_NO_CLIENT_CERT")); + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + if (peerCert == null) { + // XXX log something here. + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + // authenticate clone CA (CCA) + + String CCA_Id = null; + String CCAUserId = null; + IAuthToken token = null; + + try { + // cfu +++ authenticate checks both SUBJECT and Signer SUBJECT + CMS.debug("CloneServlet: about to authenticate"); + token = authenticate(peerCert); + // cfu maybe don't need CCA_Id, because the above check + // was good enough + CCAUserId = token.getInString("userid"); + CCA_Id = (String) peerCert.getSubjectDN().toString(); + } catch (EInvalidCredentials e) { + // already logged. + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } catch (EBaseException e) { + // already logged. + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + mAuthority.log(ILogger.LL_INFO, + "Clone Certificate Authority authenticated: " + peerCert.getSubjectDN()); + + // authorize, any authenticated user are authorized + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, token, + mAuthzResourceName, "submit"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsRequest.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + // after cert validated, check http request. + if (!method.equalsIgnoreCase("POST")) { + resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + if (len <= 0) { + resp.sendError(HttpServletResponse.SC_LENGTH_REQUIRED); + return; + } + + // now process CCA request - should just be posting revoked + // certs for now + + try { + // decode request. + CMS.debug("Cloneservlet: before decoding request, encodedreq= " + encodedreq); + msg = (IPKIMessage) mReqEncoder.decode(encodedreq); + // process request + CMS.debug("Cloneservlet: decoded request"); + replymsg = processRequest(CCA_Id, CCAUserId, msg, token); + } catch (IOException e) { + e.printStackTrace(); + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } catch (EBaseException e) { + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } + + // encode reply + String encodedrep = mReqEncoder.encode(replymsg); + + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("text/html"); + resp.setContentLength(encodedrep.length()); + + // send reply + OutputStream out = resp.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out, "UTF8"); + + writer.write(encodedrep); + writer.flush(); + writer.close(); + out.flush(); + } + + //cfu ++change this to just check the subject and signer + protected IAuthToken authenticate( + X509Certificate peerCert) + throws EBaseException { + try { + // XXX using agent authentication now since we're only + // verifying that the cert belongs to a user in the db. + // XXX change this to ACL in the future. + + // build JAVA X509Certificate from peerCert. + X509CertImpl cert = new X509CertImpl(peerCert.getEncoded()); + + AuthCredentials creds = new AuthCredentials(); + + creds.set(IAuthManager.CRED_SSL_CLIENT_CERT, + new X509Certificate[] { cert } + ); + + IAuthToken token = mAuthSubsystem.authenticate(creds, + IAuthSubsystem.CERTUSERDB_AUTHMGR_ID); + + return token; + } catch (CertificateException e) { + mAuthority.log(ILogger.LL_SECURITY, + CMS.getLogMessage("CMSGW_REMOTE_AUTHORITY_AUTH_FAILURE", peerCert.getSubjectDN().toString())); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString())); + } catch (EInvalidCredentials e) { + mAuthority.log(ILogger.LL_SECURITY, + CMS.getLogMessage("CMSGW_REMOTE_AUTHORITY_AUTH_FAILURE", peerCert.getSubjectDN().toString())); + throw e; + } catch (EBaseException e) { + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REMOTE_AUTHORITY_AUTH_FAILURE", peerCert.getSubjectDN().toString())); + throw e; + } + } + + protected IPKIMessage processRequest( + String source, String sourceUserId, IPKIMessage msg, IAuthToken token) + throws EBaseException { + IPKIMessage replymsg = null; + IRequestQueue queue = mAuthority.getRequestQueue(); + String srcid = source + ":" + msg.getReqId(); + + mAuthority.log(ILogger.LL_INFO, "CFU: in CloneServlet processRequest"); + + // find request in request queue and return result. + RequestId thisreqid = queue.findRequestBySourceId(srcid); + IRequest thisreq = null; + + if (thisreqid != null) { + thisreq = queue.findRequest(thisreqid); + if (thisreq == null) { + // strange case. + String errormsg = "Cannot find request in request queue " + thisreqid; + + mAuthority.log(ILogger.LL_FAILURE, errormsg); + throw new EBaseException(errormsg); + } else { + mAuthority.log(ILogger.LL_INFO, + "Found request " + thisreqid + " for " + srcid); + replymsg = CMS.getHttpPKIMessage(); + replymsg.fromRequest(thisreq); + return replymsg; + } + } + + // if not found process request. + thisreq = queue.newRequest(msg.getReqType()); + thisreq.setSourceId(srcid); + msg.toRequest(thisreq); + thisreq.setExtData(IRequest.AUTH_TOKEN, token); + + // setting requestor type must come after copy contents. because + // requestor is a regular attribute. + thisreq.setExtData(IRequest.REQUESTOR_TYPE, + IRequest.REQUESTOR_RA); + mAuthority.log(ILogger.LL_INFO, "Processing remote request " + srcid); + + // Set this so that request's updateBy is recorded + SessionContext s = SessionContext.getContext(); + + if (s.get(SessionContext.USER_ID) == null) { + s.put(SessionContext.USER_ID, sourceUserId); + } + + queue.processRequest(thisreq); + replymsg = CMS.getHttpPKIMessage(); + replymsg.fromRequest(thisreq); + + //for audit log + String agentID = sourceUserId; + String initiative = AuditFormat.FROMRA + " trustedManagerID: " + + agentID + " remote reqID " + msg.getReqId(); + String authMgr = AuditFormat.NOAUTH; + + if (token != null) { + authMgr = + token.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } + + // Get the certificate info from the request + X509CertInfo certInfo[] = thisreq.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + try { + if (!thisreq.getRequestStatus().equals(RequestStatus.COMPLETE)) { + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + thisreq.getRequestStatus(), + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + thisreq.getRequestStatus() } + ); + } + } else { + if (thisreq.getRequestType().equals(IRequest.CLA_CERT4CRL_REQUEST)) { + Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + CMS.debug("CloneServlet: error in CLA_CERT4CRL_REQUEST"); + } else { + // the success. + CMS.debug("CloneServlet: success in CLA_CERT4CRL_REQUEST"); + } + } + + /* cfu --- + if (thisreq.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) { + // XXX make the repeat record. + // Get the certificate(s) from the request + X509CertImpl issuedCerts[] = + (X509CertImpl[])thisreq.get(IRequest.ISSUED_CERTS); + // return potentially more than one certificates. + if (issuedCerts != null) { + for (int i = 0; i < issuedCerts.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId() , + initiative , + authMgr , + "completed", + issuedCerts[i].getSubjectDN() , + "cert issued serial number: 0x" + + issuedCerts[i].getSerialNumber().toString(16)} + ); + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId() , + initiative , + authMgr , + "completed"} + ); + } + } else if (thisreq.getRequestType().equals(IRequest.RENEWAL_REQUEST)) { + X509CertImpl[] certs = (X509CertImpl[])thisreq.get(IRequest.OLD_CERTS); + X509CertImpl old_cert = certs[0]; + certs = (X509CertImpl[])thisreq.get(IRequest.ISSUED_CERTS); + X509CertImpl renewed_cert = certs[0]; + if (old_cert != null && renewed_cert != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative , + authMgr , + "completed", + old_cert.getSubjectDN() , + old_cert.getSerialNumber().toString(16) , + "new serial number: 0x" + + renewed_cert.getSerialNumber().toString(16)} + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId() , + initiative , + authMgr , + "completed with error"} + ); + } + } else if (thisreq.getRequestType().equals(IRequest.REVOCATION_REQUEST)) { + X509CertImpl[] oldCerts = (X509CertImpl[])thisreq.get(IRequest.OLD_CERTS); + RevokedCertImpl crlentries[] = + (RevokedCertImpl[])thisreq.get(IRequest.REVOKED_CERTS); + CRLExtensions crlExts = crlentries[0].getExtensions(); + int reason = 0; + if (crlExts != null) { + Enumeration enum = crlExts.getElements(); + while(enum.hasMoreElements()){ + Extension ext = (Extension) enum.nextElement(); + if (ext instanceof CRLReasonExtension) { + reason = ((CRLReasonExtension)ext).getReason().toInt + (); + break; + } + } + } + + int count = oldCerts.length; + Integer result = (Integer)thisreq.get(IRequest.RESULT); + if (result.equals(IRequest.RES_ERROR)) { + EBaseException ex = (EBaseException)thisreq.get(IRequest.ERROR); + EBaseException[] svcErrors = + (EBaseException[])thisreq.get(IRequest.SVCERRORS); + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + EBaseException err = svcErrors[i]; + if (err != null) { + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative , + "completed with error: " + + err.toString() , + oldCerts[j].getSubjectDN() , + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString()} + ); + } + } + } + } + } + } else { + // the success. + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative , + "completed" , + oldCerts[j].getSubjectDN() , + oldCerts[j].getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString()} + ); + } + } + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId() , + initiative , + authMgr , + "completed"} + ); + } + cfu */ + } + } catch (IOException e) { + } catch (CertificateException e) { + } + + return replymsg; + } + + protected X509Certificate + getPeerCert(HttpServletRequest req) throws EBaseException { + return getSSLClientCertificate(req); + } + + public String getServletInfo() { + return INFO; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java new file mode 100644 index 000000000..e8d4f898f --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java @@ -0,0 +1,1116 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.connector; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.EInvalidCredentials; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.connector.IPKIMessage; +import com.netscape.certsrv.connector.IRequestEncoder; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.util.Utils; + +/** + * Connector servlet + * process requests from remote authority - + * service request or return status. + * + * @version $Revision$, $Date$ + */ +public class ConnectorServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 1221916495803185863L; + public static final String INFO = "Connector Servlet"; + public final static String PROP_AUTHORITY = "authority"; + protected ServletConfig mConfig = null; + protected IAuthority mAuthority = null; + protected IRequestEncoder mReqEncoder = null; + protected IAuthSubsystem mAuthSubsystem = null; + protected ILogger mLogger = CMS.getLogger(); + + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + private final static String SIGNED_AUDIT_PROTECTION_METHOD_SSL = "ssl"; + private final static String SIGNED_AUDIT_PROTECTION_METHOD_UNKNOWN = + "unknown"; + private final static String LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS = + "LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS_5"; + private final static String LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST = + "LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + + public ConnectorServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mConfig = sc; + String authority = sc.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) + CMS.getSubsystem(authority); + mReqEncoder = CMS.getHttpRequestEncoder(); + + mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + } + + public void service(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + + boolean running_state = CMS.isInRunningState(); + + if (!running_state) + throw new IOException( + "CMS server is not ready to serve."); + + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + + CMSRequest cmsRequest = newCMSRequest(); + + // set argblock + cmsRequest.setHttpParams(CMS.createArgBlock(toHashtable(request))); + + // set http request + cmsRequest.setHttpReq(request); + + // set http response + cmsRequest.setHttpResp(response); + + // set servlet config. + cmsRequest.setServletConfig(mConfig); + + // set servlet context. + cmsRequest.setServletContext(mConfig.getServletContext()); + + char[] content = null; + String encodedreq = null; + String method = null; + int len = -1; + IPKIMessage msg = null; + IPKIMessage replymsg = null; + + // NOTE must read all bufer before redoing handshake for + // ssl client auth for client auth to work. + + // get request method + method = req.getMethod(); + + // get content length + len = request.getContentLength(); + + // get content, a base 64 encoded serialized request. + if (len > 0) { + InputStream in = request.getInputStream(); + InputStreamReader inreader = new InputStreamReader(in, "UTF8"); + BufferedReader reader = new BufferedReader(inreader, len); + + content = new char[len]; + int done = reader.read(content, 0, len); + int total = done; + + while (done >= 0 && total < len) { + done = reader.read(content, total, len - total); + total += done; + } + reader.close(); + encodedreq = new String(content); + } + + // force client auth handshake, validate RA and get RA's Id. + // NOTE must do this after all contents are read for ssl + // redohandshake to work + + X509Certificate peerCert; + + try { + peerCert = getPeerCert(req); + } catch (EBaseException e) { + mAuthority.log(ILogger.LL_SECURITY, + CMS.getLogMessage("CMSGW_HAS_NO_CLIENT_CERT")); + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + if (peerCert == null) { + // XXX log something here. + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + // authenticate RA + + String RA_Id = null; + String raUserId = null; + IAuthToken token = null; + + try { + token = authenticate(request); + raUserId = token.getInString("userid"); + RA_Id = (String) peerCert.getSubjectDN().toString(); + } catch (EInvalidCredentials e) { + // already logged. + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } catch (EBaseException e) { + // already logged. + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + mAuthority.log(ILogger.LL_INFO, + "Remote Authority authenticated: " + peerCert.getSubjectDN()); + + // authorize + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, token, + mAuthzResourceName, "submit"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsRequest.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + // after cert validated, check http request. + if (!method.equalsIgnoreCase("POST")) { + resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + if (len <= 0) { + resp.sendError(HttpServletResponse.SC_LENGTH_REQUIRED); + return; + } + + // now process request. + + CMS.debug("ConnectorServlet: process request RA_Id=" + RA_Id); + try { + // decode request. + msg = (IPKIMessage) mReqEncoder.decode(encodedreq); + // process request + replymsg = processRequest(RA_Id, raUserId, msg, token); + } catch (IOException e) { + CMS.debug("ConnectorServlet: service " + e.toString()); + CMS.debug(e); + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } catch (EBaseException e) { + CMS.debug("ConnectorServlet: service " + e.toString()); + CMS.debug(e); + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } catch (Exception e) { + CMS.debug("ConnectorServlet: service " + e.toString()); + CMS.debug(e); + } + + CMS.debug("ConnectorServlet: done processRequest"); + + // encode reply + try { + String encodedrep = mReqEncoder.encode(replymsg); + + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("text/html"); + resp.setContentLength(encodedrep.length()); + + // send reply + OutputStream out = response.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out, "UTF8"); + + writer.write(encodedrep); + writer.flush(); + writer.close(); + out.flush(); + } catch (Exception e) { + CMS.debug("ConnectorServlet: error writing e=" + e.toString()); + } + CMS.debug("ConnectorServlet: send response RA_Id=" + RA_Id); + } + + public static boolean isProfileRequest(IRequest request) { + String profileId = request.getExtDataInString("profileId"); + + if (profileId == null || profileId.equals("")) + return false; + else + return true; + } + + public void normalizeProfileRequest(IRequest request) { + // if it is profile request, we need to normalize the + // x509certinfo from ra into request + X509CertInfo info = null; + ByteArrayOutputStream byteStream; + + try { + info = request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO); + + // request.set(IEnrollProfile.REQUEST_SEQ_NUM, new Integer("0")); + CertificateX509Key certKey = (CertificateX509Key) info.get(X509CertInfo.KEY); + if (certKey != null) { + byteStream = new ByteArrayOutputStream(); + certKey.encode(byteStream); + request.setExtData(IEnrollProfile.REQUEST_KEY, + byteStream.toByteArray()); + } + + CertificateSubjectName certSubject = (CertificateSubjectName) + info.get(X509CertInfo.SUBJECT); + if (certSubject != null) { + request.setExtData(IEnrollProfile.REQUEST_SUBJECT_NAME, + certSubject); + } + + CertificateValidity certValidity = (CertificateValidity) + info.get(X509CertInfo.VALIDITY); + if (certValidity != null) { + byteStream = new ByteArrayOutputStream(); + certValidity.encode(byteStream); + request.setExtData(IEnrollProfile.REQUEST_VALIDITY, + byteStream.toByteArray()); + } + + CertificateExtensions extensions = (CertificateExtensions) + info.get(X509CertInfo.EXTENSIONS); + if (extensions != null) { + request.setExtData(IEnrollProfile.REQUEST_EXTENSIONS, + extensions); + } + + CertificateAlgorithmId certAlg = (CertificateAlgorithmId) + info.get(X509CertInfo.ALGORITHM_ID); + if (certAlg != null) { + ByteArrayOutputStream certAlgOut = new ByteArrayOutputStream(); + certAlg.encode(certAlgOut); + request.setExtData(IEnrollProfile.REQUEST_SIGNING_ALGORITHM, + certAlgOut.toByteArray()); + } + } catch (Exception e) { + CMS.debug("ConnectorServlet: profile normalization " + + e.toString()); + } + + String profileId = request.getExtDataInString("profileId"); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem("profile"); + IEnrollProfile profile = null; + + // profile subsystem may not be available. In case of KRA for + // example + if (ps == null) { + CMS.debug("ConnectorServlet: Profile Subsystem not found "); + return; + } + try { + profile = (IEnrollProfile) (ps.getProfile(profileId)); + profile.setDefaultCertInfo(request); + } catch (EProfileException e) { + CMS.debug("ConnectorServlet: normalizeProfileRequest Exception: " + e.toString()); + } + if (profile == null) { + CMS.debug("ConnectorServlet: Profile not found " + profileId); + return; + } + } + + /** + * Process request + * <P> + * + * (Certificate Request - all "agent" profile cert requests made through a connector) + * <P> + * + * (Certificate Request Processed - all automated "agent" profile based cert acceptance made through a connector) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST used when a profile cert request is made (before + * approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * <li>signed.audit LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS used when inter-CIMC_Boundary data transfer is + * successful (this is used when data does not need to be captured) + * </ul> + * + * @param source string containing source + * @param sourceUserId string containing source user ID + * @param msg PKI message + * @param token the authentication token + * @exception EBaseException an error has occurred + * @return PKI message + */ + protected IPKIMessage processRequest( + String source, String sourceUserId, IPKIMessage msg, IAuthToken token) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = sourceUserId; + String auditProtectionMethod = SIGNED_AUDIT_PROTECTION_METHOD_SSL; + String auditRequestType = msg.getReqType(); + String auditRequesterID = msg.getReqId(); + + // additional parms for LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String subject = null; + + // additional parms for LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED + String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + // "normalize" the "auditSubjectID" + if (auditSubjectID != null) { + auditSubjectID = auditSubjectID.trim(); + } else { + auditSubjectID = ILogger.UNIDENTIFIED; + } + + // "normalize" the "auditRequestType" + if (auditRequestType != null) { + auditRequestType = auditRequestType.trim(); + } else { + auditRequestType = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + // "normalize" the "auditRequesterID" + if (auditRequesterID != null) { + auditRequesterID = auditRequesterID.trim(); + } else { + auditRequesterID = ILogger.UNIDENTIFIED; + } + + IPKIMessage replymsg = null; + + try { + IRequestQueue queue = mAuthority.getRequestQueue(); + String srcid = source + ":" + msg.getReqId(); + + // find request in request queue and return result. + RequestId thisreqid = queue.findRequestBySourceId(srcid); + IRequest thisreq = null; + + if (thisreqid != null) { + thisreq = queue.findRequest(thisreqid); + if (thisreq == null) { + // strange case. + String errormsg = "Cannot find request in request queue " + + thisreqid; + + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage( + "CMSGW_REQUEST_ID_NOT_FOUND_1", + thisreqid.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // does not yet matter at this point! + + throw new EBaseException(errormsg); + } else { + mAuthority.log(ILogger.LL_INFO, + "Found request " + thisreqid + " for " + srcid); + replymsg = CMS.getHttpPKIMessage(); + replymsg.fromRequest(thisreq); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // does not yet matter at this point! + + return replymsg; + } + } + + // if not found process request. + thisreq = queue.newRequest(msg.getReqType()); + CMS.debug("ConnectorServlet: created requestId=" + + thisreq.getRequestId().toString()); + thisreq.setSourceId(srcid); + + // NOTE: For the following signed audit message, since we only + // care about the "msg.toRequest( thisreq );" command, and + // since this command does not throw an EBaseException + // (which is the only exception designated by this method), + // then this code does NOT need to be contained within its + // own special try/catch block. + msg.toRequest(thisreq); + + if (isProfileRequest(thisreq)) { + X509CertInfo info = + thisreq.getExtDataInCertInfo( + IEnrollProfile.REQUEST_CERTINFO); + + try { + CertificateSubjectName sn = (CertificateSubjectName) + info.get(X509CertInfo.SUBJECT); + + // if the cert subject name is NOT MISSING, retrieve the + // actual "auditCertificateSubjectName" and "normalize" + // it + if (sn != null) { + subject = sn.toString(); + if (subject != null) { + // NOTE: This is ok even if the cert subject + // name is "" (empty)! + auditCertificateSubjectName = subject.trim(); + } + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditProfileID(), + auditCertificateSubjectName); + + audit(auditMessage); + } catch (CertificateException e) { + CMS.debug("ConnectorServlet: processRequest " + + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditProfileID(), + auditCertificateSubjectName); + + audit(auditMessage); + } catch (IOException e) { + CMS.debug("ConnectorServlet: processRequest " + + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditProfileID(), + auditCertificateSubjectName); + + audit(auditMessage); + } + } + + thisreq.setExtData(IRequest.AUTH_TOKEN, token); + + // setting requestor type must come after copy contents. because + // requestor is a regular attribute. + thisreq.setExtData(IRequest.REQUESTOR_TYPE, + IRequest.REQUESTOR_RA); + mAuthority.log(ILogger.LL_INFO, "Processing remote request " + + srcid); + + // Set this so that request's updateBy is recorded + SessionContext s = SessionContext.getContext(); + + if (s.get(SessionContext.USER_ID) == null) { + s.put(SessionContext.USER_ID, sourceUserId); + } + + if (s.get(SessionContext.REQUESTER_ID) == null) { + s.put(SessionContext.REQUESTER_ID, msg.getReqId()); + } + + CMS.debug("ConnectorServlet: calling processRequest instance=" + + thisreq); + if (isProfileRequest(thisreq)) { + normalizeProfileRequest(thisreq); + } + + try { + queue.processRequest(thisreq); + + if (isProfileRequest(thisreq)) { + // reset the "auditInfoCertValue" + auditInfoCertValue = auditInfoCertValue(thisreq); + + if (auditInfoCertValue != null) { + if (!(auditInfoCertValue.equals( + ILogger.SIGNED_AUDIT_EMPTY_VALUE))) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue); + + audit(auditMessage); + } + } + } + } catch (EBaseException eAudit1) { + if (isProfileRequest(thisreq)) { + // reset the "auditInfoCertValue" + auditInfoCertValue = auditInfoCertValue(thisreq); + + if (auditInfoCertValue != null) { + if (!(auditInfoCertValue.equals( + ILogger.SIGNED_AUDIT_EMPTY_VALUE))) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue); + + audit(auditMessage); + } + } + } + + // rethrow EBaseException to primary catch clause + // within this method + throw eAudit1; + } + + replymsg = CMS.getHttpPKIMessage(); + replymsg.fromRequest(thisreq); + + CMS.debug("ConnectorServlet: replymsg.reqStatus=" + + replymsg.getReqStatus()); + + //for audit log + String agentID = sourceUserId; + String initiative = AuditFormat.FROMRA + " trustedManagerID: " + + agentID + " remote reqID " + msg.getReqId(); + String authMgr = AuditFormat.NOAUTH; + + if (token != null) { + authMgr = + token.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } + + if (isProfileRequest(thisreq)) { + // XXX audit log + CMS.debug("ConnectorServlet: done requestId=" + + thisreq.getRequestId().toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // has already been logged at this point! + + return replymsg; + } + + // Get the certificate info from the request + X509CertInfo x509Info[] = thisreq.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + try { + if (!thisreq.getRequestStatus().equals(RequestStatus.COMPLETE)) { + if (x509Info != null) { + for (int i = 0; i < x509Info.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + thisreq.getRequestStatus(), + x509Info[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + thisreq.getRequestStatus() } + ); + } + } else { + if (thisreq.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) { + // XXX make the repeat record. + // Get the certificate(s) from the request + X509CertImpl x509Certs[] = null; + + if (x509Info != null) + x509Certs = + thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + // return potentially more than one certificates. + if (x509Certs != null) { + for (int i = 0; i < x509Certs.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed", + x509Certs[i].getSubjectDN(), + "cert issued serial number: 0x" + + x509Certs[i].getSerialNumber().toString(16) } + ); + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed" } + ); + } + } else if (thisreq.getRequestType().equals(IRequest.RENEWAL_REQUEST)) { + X509CertImpl[] certs = + thisreq.getExtDataInCertArray(IRequest.OLD_CERTS); + X509CertImpl old_cert = certs[0]; + + certs = thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS); + X509CertImpl renewed_cert = certs[0]; + + if (old_cert != null && renewed_cert != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative, + authMgr, + "completed", + old_cert.getSubjectDN(), + old_cert.getSerialNumber().toString(16), + "new serial number: 0x" + + renewed_cert.getSerialNumber().toString(16) } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed with error" } + ); + } + } else if (thisreq.getRequestType().equals(IRequest.REVOCATION_REQUEST)) { + Certificate[] oldCerts = + thisreq.getExtDataInCertArray(IRequest.OLD_CERTS); + RevokedCertImpl crlentries[] = + thisreq.getExtDataInRevokedCertArray(IRequest.REVOKED_CERTS); + CRLExtensions crlExts = crlentries[0].getExtensions(); + int reason = 0; + + if (crlExts != null) { + Enumeration<Extension> enum1 = crlExts.getElements(); + + while (enum1.hasMoreElements()) { + Extension ext = enum1.nextElement(); + + if (ext instanceof CRLReasonExtension) { + reason = ((CRLReasonExtension) ext).getReason().toInt(); + break; + } + } + } + + int count = oldCerts.length; + Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + String[] svcErrors = + thisreq.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative, + "completed with error: " + + err, + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + } + } + } else { + // the success. + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative, + "completed", + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString() } + ); + } + } + } + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed" } + ); + } + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } catch (IOException e) { + CMS.debug("ConnectorServlet: process " + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } catch (CertificateException e) { + CMS.debug("ConnectorServlet: process " + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } catch (Exception e) { + CMS.debug("ConnectorServlet: process " + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } finally { + SessionContext.releaseContext(); + } + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // has already been logged at this point! + + return replymsg; + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // has either already been logged, or + // does not yet matter at this point! + + return replymsg; + } + } + + protected X509Certificate + getPeerCert(HttpServletRequest req) throws EBaseException { + return getSSLClientCertificate(req); + } + + public String getServletInfo() { + return INFO; + } + + /** + * Signed Audit Log + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to store messages to the signed audit log. + * <P> + * + * @param msg signed audit log message + */ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (mSignedAuditLogger == null) { + return; + } + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Profile ID + * + * This method is inherited by all extended "EnrollProfile"s, + * and is called to obtain the "ProfileID" for + * a signed audit log message. + * <P> + * + * @return id string containing the signed audit log message ProfileID + */ + protected String auditProfileID() { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String profileID = getId(); + + if (profileID != null) { + profileID = profileID.trim(); + } else { + profileID = ILogger.UNIDENTIFIED; + } + + return profileID; + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param request a Request containing an X509CertImpl + * @return cert string containing the certificate + */ + private String auditInfoCertValue(IRequest request) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + X509CertImpl x509cert = request.getExtDataInCert( + IEnrollProfile.REQUEST_ISSUED_CERT); + + if (x509cert == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + byte rawData[] = null; + + try { + rawData = x509cert.getEncoded(); + } catch (CertificateEncodingException e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + String cert = null; + + // convert "rawData" into "base64Data" + if (rawData != null) { + String base64Data = null; + + base64Data = Utils.base64encode(rawData).trim(); + + StringBuffer sb = new StringBuffer(); + // extract all line separators from the "base64Data" + for (int i = 0; i < base64Data.length(); i++) { + if (base64Data.substring(i, i).getBytes() != EOL) { + sb.append(base64Data.substring(i, i)); + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java b/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java new file mode 100644 index 000000000..bb787c7ad --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java @@ -0,0 +1,292 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.connector; + +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IPrettyPrintFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; + +/** + * GenerateKeyPairServlet + * handles "server-side key pair generation" requests from the + * netkey RA. + * + * @author Christina Fu (cfu) + * @version $Revision$, $Date$ + */ +//XXX add auditing later +public class GenerateKeyPairServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 4308385291961910458L; + private final static String INFO = "GenerateKeyPairServlet"; + public final static String PROP_AUTHORITY = "authority"; + protected ServletConfig mConfig = null; + protected IAuthority mAuthority = null; + public static int ERROR = 1; + IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":"); + protected IAuthSubsystem mAuthSubsystem = null; + protected ILogger mLogger = CMS.getLogger(); + + /** + * Constructs GenerateKeyPair servlet. + * + */ + public GenerateKeyPairServlet() { + super(); + } + + public void init(ServletConfig config) throws ServletException { + super.init(config); + mConfig = config; + String authority = config.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) + CMS.getSubsystem(authority); + + mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + } + + /** + * Returns serlvet information. + * + * @return name of this servlet + */ + public String getServletInfo() { + return INFO; + } + + /* + * processServerSideKeyGen - + * handles netkey DRM serverside keygen. + * netkey operations: + * 1. generate keypair (archive user priv key) + * 2. unwrap des key with transport key, then url decode it + * 3. wrap user priv key with des key + * 4. send the following to RA: + * * des key wrapped(user priv key) + * * user public key + * (note: RA should have kek-wrapped des key from TKS) + * * recovery blob (used for recovery) + */ + private void processServerSideKeyGen(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + IRequestQueue queue = mAuthority.getRequestQueue(); + IRequest thisreq = null; + + boolean missingParam = false; + String status = "0"; + + CMS.debug("processServerSideKeyGen begins:"); + + String rCUID = req.getParameter("CUID"); + String rUserid = req.getParameter("userid"); + String rdesKeyString = req.getParameter("drm_trans_desKey"); + String rArchive = req.getParameter("archive"); + String rKeysize = req.getParameter("keysize"); + + if ((rCUID == null) || (rCUID.equals(""))) { + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: CUID"); + missingParam = true; + } + + if ((rUserid == null) || (rUserid.equals(""))) { + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: userid"); + missingParam = true; + } + + if ((rKeysize == null) || (rKeysize.equals(""))) { + rKeysize = "1024"; // default to 1024 + } + + if ((rdesKeyString == null) || + (rdesKeyString.equals(""))) { + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing request parameter: DRM-transportKey-wrapped DES key"); + missingParam = true; + } + + if ((rArchive == null) || (rArchive.equals(""))) { + CMS.debug("GenerateKeyPairServlet: processServerSideKeygen(): missing key archival flag 'archive' ,default to true"); + rArchive = "true"; + } + + if (!missingParam) { + thisreq = queue.newRequest(IRequest.NETKEY_KEYGEN_REQUEST); + + thisreq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_NETKEY_RA); + thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID); + thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid); + thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString); + thisreq.setExtData(IRequest.NETKEY_ATTR_ARCHIVE_FLAG, rArchive); + thisreq.setExtData(IRequest.NETKEY_ATTR_KEY_SIZE, rKeysize); + + queue.processRequest(thisreq); + Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); + if (result != null) { + // sighs! tps thinks 0 is good, and DRM thinks 1 is good + if (result.intValue() == 1) + status = "0"; + else + status = result.toString(); + } else + status = "7"; + + CMS.debug("processServerSideKeygen finished"); + } // ! missingParam + + String value = ""; + + resp.setContentType("text/html"); + + String wrappedPrivKeyString = ""; + String publicKeyString = ""; + + if (thisreq == null) { + CMS.debug("GenerateKeyPairServlet::processServerSideKeyGen() - " + + "thisreq is null!"); + throw new EBaseException("thisreq is null"); + } + + publicKeyString = thisreq.getExtDataInString("public_key"); + wrappedPrivKeyString = thisreq.getExtDataInString("wrappedUserPrivate"); + + String ivString = thisreq.getExtDataInString("iv_s"); + + /* + if (selectedToken == null) + status = "4"; + */ + if (!status.equals("0")) + value = "status=" + status; + else { + StringBuffer sb = new StringBuffer(); + sb.append("status=0&"); + sb.append("wrapped_priv_key="); + sb.append(wrappedPrivKeyString); + sb.append("&iv_param="); + sb.append(ivString); + sb.append("&public_key="); + sb.append(publicKeyString); + value = sb.toString(); + + } + CMS.debug("processServerSideKeyGen:outputString.encode " + value); + + try { + resp.setContentLength(value.length()); + CMS.debug("GenerateKeyPairServlet:outputString.length " + value.length()); + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (IOException e) { + CMS.debug("GenerateKeyPairServlet: " + e.toString()); + } + } + + /* + + * For GenerateKeyPair: + * + * input: + * CUID=value0 + * trans-wrapped-desKey=value1 + * + * output: + * status=value0 + * publicKey=value1 + * desKey-wrapped-userPrivateKey=value2 + * proofOfArchival=value3 + */ + + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "execute"); + } catch (Exception e) { + } + + if (authzToken == null) { + + try { + resp.setContentType("text/html"); + String value = "unauthorized="; + CMS.debug("GenerateKeyPairServlet: Unauthorized"); + + resp.setContentLength(value.length()); + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (Exception e) { + CMS.debug("GenerateKeyPairServlet: " + e.toString()); + } + + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + // begin Netkey serverSideKeyGen and archival + CMS.debug("GenerateKeyPairServlet: processServerSideKeyGen would be called"); + processServerSideKeyGen(req, resp); + return; + // end Netkey functions + + } + + /** + * XXX remember tocheck peer SSL cert and get RA id later + * + * Serves HTTP admin request. + * + * @param req HTTP request + * @param resp HTTP response + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java b/base/common/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java new file mode 100644 index 000000000..337b24259 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java @@ -0,0 +1,326 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.connector; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IPrettyPrintFormat; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; + +/** + * TokenKeyRecoveryServlet + * handles "key recovery service" requests from the + * netkey TPS + * + * @author Christina Fu (cfu) + * @version $Revision$, $Date$ + */ +//XXX add auditing later +public class TokenKeyRecoveryServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -2322410659376501336L; + private final static String INFO = "TokenKeyRecoveryServlet"; + public final static String PROP_AUTHORITY = "authority"; + protected ServletConfig mConfig = null; + protected IAuthority mAuthority = null; + public static int ERROR = 1; + IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":"); + protected IAuthSubsystem mAuthSubsystem = null; + + /** + * Constructs TokenKeyRecovery servlet. + * + */ + public TokenKeyRecoveryServlet() { + super(); + } + + public void init(ServletConfig config) throws ServletException { + super.init(config); + mConfig = config; + String authority = config.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) + CMS.getSubsystem(authority); + + mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + } + + /** + * Returns serlvet information. + * + * @return name of this servlet + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * + * @param s The URL to decode + */ + protected String URLdecode(String s) { + if (s == null) + return null; + ByteArrayOutputStream out = new ByteArrayOutputStream(s.length()); + + for (int i = 0; i < s.length(); i++) { + int c = (int) s.charAt(i); + + if (c == '+') { + out.write(' '); + } else if (c == '%') { + int c1 = Character.digit(s.charAt(++i), 16); + int c2 = Character.digit(s.charAt(++i), 16); + + out.write((char) (c1 * 16 + c2)); + } else { + out.write(c); + } + } // end for + return out.toString(); + } + + /* + * processTokenKeyRecovery + * handles netkey key recovery requests + * input params are: + * CUID - the CUID of the old token where the keys/certs were initially for + * userid - the userid that belongs to both the old token and the new token + * drm_trans_desKey - the des key generated for the NEW token + * wrapped with DRM transport key + * cert - the user cert corresponding to the key to be recovered + * + * operations: + * 1. unwrap des key with transport key, then url decode it + * 2. retrieve user private key + * 3. wrap user priv key with des key + * 4. send the following to RA: + * * des key wrapped(user priv key) + * (note: RA should have kek-wrapped des key from TKS) + * * recovery blob (used for recovery) + * + * output params are: + * status=value0 + * publicKey=value1 + * desKey-wrapped-userPrivateKey=value2 + */ + private void processTokenKeyRecovery(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + IRequestQueue queue = mAuthority.getRequestQueue(); + IRequest thisreq = null; + + // IConfigStore sconfig = CMS.getConfigStore(); + boolean missingParam = false; + String status = "0"; + + CMS.debug("processTokenKeyRecovery begins:"); + + String rCUID = req.getParameter("CUID"); + String rUserid = req.getParameter("userid"); + String rdesKeyString = req.getParameter("drm_trans_desKey"); + String rCert = req.getParameter("cert"); + + if ((rCUID == null) || (rCUID.equals(""))) { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: CUID"); + missingParam = true; + } + + if ((rUserid == null) || (rUserid.equals(""))) { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: userid"); + missingParam = true; + } + + if ((rdesKeyString == null) || + (rdesKeyString.equals(""))) { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: DRM-transportKey-wrapped des key"); + missingParam = true; + } + + if ((rCert == null) || (rCert.equals(""))) { + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery(): missing request parameter: cert"); + missingParam = true; + } + + if (!missingParam) { + thisreq = queue.newRequest(IRequest.NETKEY_KEYRECOVERY_REQUEST); + + thisreq.setExtData(IRequest.REQUESTOR_TYPE, IRequest.REQUESTOR_NETKEY_RA); + thisreq.setExtData(IRequest.NETKEY_ATTR_CUID, rCUID); + thisreq.setExtData(IRequest.NETKEY_ATTR_USERID, rUserid); + thisreq.setExtData(IRequest.NETKEY_ATTR_DRMTRANS_DES_KEY, rdesKeyString); + thisreq.setExtData(IRequest.NETKEY_ATTR_USER_CERT, rCert); + + //XXX auto process for netkey + queue.processRequest(thisreq); + // IService svc = (IService) new TokenKeyRecoveryService(kra); + // svc.serviceRequest(thisreq); + + Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); + if (result != null) { + // sighs! tps thinks 0 is good, and drm thinks 1 is good + if (result.intValue() == 1) + status = "0"; + else + status = result.toString(); + } else + status = "7"; + + CMS.debug("processTokenKeyRecovery finished"); + } // ! missingParam + + String value = ""; + + resp.setContentType("text/html"); + + String wrappedPrivKeyString = ""; + String publicKeyString = ""; + String ivString = ""; + /* if is RECOVERY_PROTOTYPE + String recoveryBlobString = ""; + + IKeyRecord kr = (IKeyRecord) thisreq.get("keyRecord"); + byte publicKey_b[] = kr.getPublicKeyData(); + + BigInteger serialNo = kr.getSerialNumber(); + + String serialNumberString = + com.netscape.cmsutil.util.Utils.SpecialEncode(serialNo.toByteArray()); + + recoveryBlobString = (String) + thisreq.get("recoveryBlob"); + */ + + if (thisreq == null) { + CMS.debug("TokenKeyRecoveryServlet::processTokenKeyRecovery() - " + + "thisreq is null!"); + throw new EBaseException("thisreq is null"); + } + + publicKeyString = thisreq.getExtDataInString("public_key"); + wrappedPrivKeyString = thisreq.getExtDataInString("wrappedUserPrivate"); + + ivString = thisreq.getExtDataInString("iv_s"); + /* + if (selectedToken == null) + status = "4"; + */ + if (!status.equals("0")) + value = "status=" + status; + else { + StringBuffer sb = new StringBuffer(); + sb.append("status=0&"); + sb.append("wrapped_priv_key="); + sb.append(wrappedPrivKeyString); + sb.append("&public_key="); + sb.append(publicKeyString); + sb.append("&iv_param="); + sb.append(ivString); + value = sb.toString(); + + } + CMS.debug("ProcessTokenKeyRecovery:outputString.encode " + value); + + try { + resp.setContentLength(value.length()); + CMS.debug("TokenKeyRecoveryServlet:outputString.length " + value.length()); + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (IOException e) { + CMS.debug("TokenKeyRecoveryServlet: " + e.toString()); + } + } + + /* + * For TokenKeyRecovery + * + * input: + * CUID=value0 + * trans-wrapped-desKey=value1 + * + * output: + * status=value0 + * publicKey=value1 + * desKey-wrapped-userPrivateKey=value2 + * proofOfArchival=value3 + */ + + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "submit"); + } catch (Exception e) { + } + + if (authzToken == null) { + + try { + resp.setContentType("text/html"); + String value = "unauthorized="; + CMS.debug("TokenKeyRecoveryServlet: Unauthorized"); + + resp.setContentLength(value.length()); + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (Exception e) { + CMS.debug("TokenKeyRecoveryServlet: " + e.toString()); + } + + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + // begin Netkey serverSideKeyGen and archival + CMS.debug("TokenKeyRecoveryServlet: processTokenKeyRecovery would be called"); + processTokenKeyRecovery(req, resp); + return; + // end Netkey functions + + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/AdminAuthenticatePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/AdminAuthenticatePanel.java new file mode 100644 index 000000000..585d444d4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/AdminAuthenticatePanel.java @@ -0,0 +1,330 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.X509Certificate; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class AdminAuthenticatePanel extends WizardPanelBase { + + public AdminAuthenticatePanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Admin Authentication"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Admin Authentication"); + setId(id); + } + + public boolean isSubPanel() { + return true; + } + + /** + * Should we skip this panel for the configuration. + */ + public boolean shouldSkip() { + CMS.debug("AdminAuthenticatePanel: should skip"); + + IConfigStore cs = CMS.getConfigStore(); + // if we are root, no need to get the certificate chain. + + try { + String select = cs.getString("preop.subsystem.select", ""); + if (select.equals("new")) { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + /* clean up if necessary */ + try { + @SuppressWarnings("unused") + boolean done = cs.getBoolean("preop.AdminAuthenticate.done"); // check for errors + cs.putBoolean("preop.AdminAuthenticate.done", false); + cs.commit(false); + } catch (Exception e) { + } + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.AdminAuthenticate.done", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Admin Authentication"); + IConfigStore config = CMS.getConfigStore(); + + if (isPanelDone()) { + + try { + String s = config.getString("preop.master.admin.uid", ""); + String type = config.getString("preop.subsystem.select", ""); + if (type.equals("clone")) + context.put("uid", s); + else + context.put("uid", ""); + } catch (Exception e) { + CMS.debug(e.toString()); + } + } else { + context.put("uid", ""); + } + + context.put("password", ""); + context.put("panel", "admin/console/config/adminauthenticatepanel.vm"); + context.put("errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + String subsystemtype = ""; + String cstype = ""; + try { + subsystemtype = config.getString("preop.subsystem.select", ""); + cstype = config.getString("cs.type", ""); + } catch (Exception e) { + } + cstype = toLowerCaseSubsystemType(cstype); + + if (subsystemtype.equals("clone")) { + CMS.debug("AdminAuthenticatePanel: this is the clone subsystem"); + String uid = HttpInput.getUID(request, "uid"); + if (uid == null) { + context.put("errorString", "Uid is empty"); + throw new IOException("Uid is empty"); + } + context.put("uid", uid); + String pwd = HttpInput.getPassword(request, "__password"); + config.putString("preop.master.admin.uid", uid); + config.putString("preop.master.admin.pwd", pwd); + String host = ""; + int httpsport = -1; + try { + host = config.getString("preop.master.hostname"); + } catch (Exception e) { + CMS.debug("AdminAuthenticatePanel update: " + e.toString()); + context.put("errorString", "Missing hostname for master"); + throw new IOException("Missing hostname"); + } + + try { + httpsport = config.getInteger("preop.master.httpsadminport"); + } catch (Exception e) { + CMS.debug("AdminAuthenticatePanel update: " + e.toString()); + context.put("errorString", "Missing port for master"); + throw new IOException("Missing port"); + } + + String list = ""; + try { + list = config.getString("preop.cert.list", ""); + } catch (Exception e) { + } + + StringBuffer c1 = new StringBuffer(); + StringBuffer s1 = new StringBuffer(); + + StringTokenizer tok = new StringTokenizer(list, ","); + while (tok.hasMoreTokens()) { + String t1 = tok.nextToken(); + c1.append(","); + c1.append("cloning."); + c1.append(t1); + c1.append(".nickname,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".dn,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".keytype,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".keyalgorithm,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".privkey.id,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".pubkey.exponent,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".pubkey.modulus,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".pubkey.encoded"); + + if (s1.length() != 0) + s1.append(","); + + s1.append(cstype); + s1.append("."); + s1.append(t1); + } + + if (!cstype.equals("ca")) { + c1.append(",preop.ca.hostname,preop.ca.httpport,preop.ca.httpsport,preop.ca.list,preop.ca.pkcs7,preop.ca.type"); + } + s1.append(",internaldb,internaldb.ldapauth,internaldb.ldapconn"); + String content = + "uid=" + uid + + "&pwd=" + pwd + + "&op=get&names=cloning.module.token,instanceId," + + "internaldb.ldapauth.password,internaldb.replication.password" + + c1.toString() + "&substores=" + s1.toString(); + + boolean success = updateConfigEntries(host, httpsport, true, + "/" + cstype + "/admin/" + cstype + "/getConfigEntries", content, config, + response); + + try { + config.commit(false); + } catch (Exception ee) { + } + + if (!success) { + context.put("errorString", "Failed to get configuration entries from the master"); + throw new IOException("Failed to get configuration entries from the master"); + } else { + boolean cloneReady = isCertdbCloned(request, context); + if (!cloneReady) { + CMS.debug("AdminAuthenticatePanel update: clone does not have all the certificates."); + context.put("errorString", "Make sure you have copied the certificate database over to the clone"); + throw new IOException("Clone is not ready"); + } + } + } else { + CMS.debug("AdminAuthentication update: no authentication is required."); + } + + config.putBoolean("preop.AdminAuthenticate.done", true); + try { + config.commit(false); + } catch (EBaseException e) { + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Admin Authentication"); + context.put("password", ""); + context.put("panel", "admin/console/config/adminauthenticatepanel.vm"); + } + + private boolean isCertdbCloned(HttpServletRequest request, + Context context) { + IConfigStore config = CMS.getConfigStore(); + String certList = ""; + try { + CryptoManager cm = CryptoManager.getInstance(); + certList = config.getString("preop.cert.list"); + StringTokenizer st = new StringTokenizer(certList, ","); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + String tokenname = config.getString("preop.module.token", ""); + cm.getTokenByName(tokenname); // throw exception on error + String name1 = "preop.master." + token + ".nickname"; + String nickname = config.getString(name1, ""); + if (!tokenname.equals("Internal Key Storage Token") && + !tokenname.equals("internal")) + nickname = tokenname + ":" + nickname; + + CMS.debug("AdminAuthenticatePanel isCertdbCloned: " + nickname); + X509Certificate cert = cm.findCertByNickname(nickname); + if (cert == null) + return false; + } + } catch (Exception e) { + context.put("errorString", "Check your CS.cfg for cloning"); + return false; + } + + return true; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/AdminPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/AdminPanel.java new file mode 100644 index 000000000..1f5a3327c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/AdminPanel.java @@ -0,0 +1,690 @@ +// --- 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.csadmin; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URLEncoder; +import java.security.cert.X509Certificate; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPException; +import netscape.security.pkcs.ContentInfo; +import netscape.security.pkcs.PKCS10; +import netscape.security.pkcs.PKCS7; +import netscape.security.pkcs.SignerInfo; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.asn1.SEQUENCE; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.http.HttpClient; +import com.netscape.cmsutil.http.HttpRequest; +import com.netscape.cmsutil.http.HttpResponse; +import com.netscape.cmsutil.http.JssSSLSocketFactory; +import com.netscape.cmsutil.xml.XMLObject; + +public class AdminPanel extends WizardPanelBase { + + private static final String ADMIN_UID = "admin"; + private final static String CERT_TAG = "admin"; + + public AdminPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Administrator"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) { + setPanelNo(panelno); + setName("Administrator"); + setId(id); + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.admin.email", ""); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.admin.email", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (Exception e) { + } + + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + Descriptor emailDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "Email address for an administrator"); + + set.add("admin_email", emailDesc); + + Descriptor pwdDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "Administrator's password"); + + set.add("pwd", pwdDesc); + + Descriptor pwdAgainDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "Administrator's password again"); + + set.add("admin_password_again", pwdAgainDesc); + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("AdminPanel: display"); + + IConfigStore cs = CMS.getConfigStore(); + String session_id = request.getParameter("session_id"); + if (session_id != null) { + CMS.debug("NamePanel setting session id."); + CMS.setConfigSDSessionId(session_id); + } + + String type = ""; + String info = ""; + context.put("import", "true"); + + try { + type = cs.getString("preop.ca.type", ""); + } catch (Exception e) { + } + + if (isPanelDone()) { + try { + context.put("admin_email", cs.getString("preop.admin.email")); + context.put("admin_name", cs.getString("preop.admin.name")); + context.put("admin_pwd", ""); + context.put("admin_pwd_again", ""); + context.put("admin_uid", cs.getString("preop.admin.uid")); + } catch (Exception e) { + } + } else { + String def_admin_name = ""; + try { + def_admin_name = cs.getString("cs.type") + " Administrator of Instance " + cs.getString("instanceId"); + } catch (EBaseException e) { + } + context.put("admin_name", def_admin_name); + context.put("admin_email", ""); + context.put("admin_pwd", ""); + context.put("admin_pwd_again", ""); + context.put("admin_uid", ADMIN_UID); + } + ISubsystem ca = (ISubsystem) CMS.getSubsystem("ca"); + + if (ca == null) { + context.put("ca", "false"); + } else { + context.put("ca", "true"); + } + context.put("caType", type); + + String domainname = ""; + try { + domainname = cs.getString("securitydomain.name", ""); + } catch (EBaseException e1) { + } + context.put("securityDomain", domainname); + context.put("title", "Administrator"); + context.put("panel", "admin/console/config/adminpanel.vm"); + context.put("errorString", ""); + context.put("info", info); + + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + String pwd = HttpInput.getPassword(request, "__pwd"); + String pwd_again = HttpInput.getPassword(request, "__admin_password_again"); + String email = HttpInput.getEmail(request, "email"); + String name = HttpInput.getName(request, "name"); + String uid = HttpInput.getUID(request, "uid"); + context.put("admin_email", email); + context.put("admin_name", name); + context.put("admin_pwd", pwd); + context.put("admin_pwd_again", pwd_again); + context.put("import", "true"); + + if (name == null || name.equals("")) { + context.put("updateStatus", "validate-failure"); + throw new IOException("Name is empty"); + } + + if (email == null || email.equals("")) { + context.put("updateStatus", "validate-failure"); + throw new IOException("Email is empty"); + } + + if (uid == null || uid.equals("")) { + context.put("updateStatus", "validate-failure"); + throw new IOException("Uid is empty"); + } + + if (!pwd.equals(pwd_again)) { + context.put("updateStatus", "validate-failure"); + throw new IOException("Password and password again are not the same."); + } + + if (email == null || email.length() == 0) { + context.put("updateStatus", "validate-failure"); + throw new IOException("Email address is empty string."); + } + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + context.put("info", ""); + context.put("import", "true"); + + String type = ""; + String subsystemtype = ""; + String selected_hierarchy = ""; + try { + type = config.getString(PRE_CA_TYPE, ""); + subsystemtype = config.getString("cs.type", ""); + selected_hierarchy = config.getString("preop.hierarchy.select", ""); + } catch (Exception e) { + } + + ISubsystem ca = (ISubsystem) CMS.getSubsystem("ca"); + + if (ca == null) { + context.put("ca", "false"); + } else { + context.put("ca", "true"); + } + context.put("caType", type); + String uid = HttpInput.getUID(request, "uid"); + String email = HttpInput.getEmail(request, "email"); + String name = HttpInput.getName(request, "name"); + + CMS.debug("AdminPanel update: email address = " + email); + + config.putString("preop.admin.uid", uid); + config.putString("preop.admin.email", email); + config.putString("preop.admin.name", name); + try { + createAdmin(request); + } catch (IOException e) { + context.put("errorString", "Failed to create administrator."); + context.put("updateStatus", "failure"); + throw e; + } + + // REMINDER: This panel is NOT used by "clones" + if (ca != null) { + if (selected_hierarchy.equals("root")) { + CMS.debug("AdminPanel update: " + + "Root CA subsystem"); + } else { + CMS.debug("AdminPanel update: " + + "Subordinate CA subsystem"); + } + + try { + createAdminCertificate(request, response, context); + } catch (IOException e) { + CMS.debug("AdminPanel update: Exception: " + e.toString()); + context.put("errorString", + "Failed to create administrator certificate."); + context.put("updateStatus", "failure"); + throw e; + } + } else { + String ca_hostname = null; + int ca_port = -1; + + // REMINDER: This panel is NOT used by "clones" + CMS.debug("AdminPanel update: " + + subsystemtype + + " subsystem"); + + if (type.equals("sdca")) { + try { + ca_hostname = config.getString("preop.ca.hostname"); + ca_port = config.getInteger("preop.ca.httpsport"); + } catch (Exception e) { + } + } else { + try { + ca_hostname = config.getString("securitydomain.host", ""); + ca_port = config.getInteger("securitydomain.httpseeport"); + } catch (Exception e) { + } + } + + submitRequest(ca_hostname, ca_port, request, response, context); + } + + try { + CMS.reinit(IUGSubsystem.ID); + } catch (Exception e) { + CMS.debug("AdminPanel update: " + e.toString()); + } + + try { + config.commit(false); + } catch (Exception e) { + } + + context.put("updateStatus", "success"); + + } + + private void createAdmin(HttpServletRequest request) throws IOException { + IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID)); + IConfigStore config = CMS.getConfigStore(); + String groupName = null; + + try { + groupName = config.getString(PRE_CONF_AGENT_GROUP, + "Certificate Manager Agents"); + } catch (Exception e) { + CMS.debug("AdminPanel createAdmin: " + e.toString()); + } + + IUser user = null; + String uid = HttpInput.getUID(request, "uid"); + + try { + user = system.createUser(uid); + String email = HttpInput.getEmail(request, "email"); + String name = HttpInput.getName(request, "name"); + String pwd = HttpInput.getPassword(request, "__pwd"); + + user.setEmail(email); + user.setPassword(pwd); + user.setFullName(name); + user.setUserType("adminType"); + user.setState("1"); + user.setPhone(""); + system.addUser(user); + } catch (LDAPException e) { + CMS.debug("AdminPanel createAdmin: addUser " + e.toString()); + if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) { + throw new IOException(e.toString()); + } + } catch (Exception e) { + CMS.debug("AdminPanel createAdmin: addUser " + e.toString()); + throw new IOException(e.toString()); + } + + IGroup group = null; + + try { + group = system.getGroupFromName(groupName); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + group = system.getGroupFromName("Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + + String select = config.getString("securitydomain.select", ""); + if (select.equals("new")) { + group = system.getGroupFromName("Security Domain Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise CA Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise KRA Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise RA Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise TKS Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise OCSP Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + + group = system.getGroupFromName("Enterprise TPS Administrators"); + if (!group.isMember(uid)) { + group.addMemberName(uid); + system.modifyGroup(group); + } + } + } catch (Exception e) { + CMS.debug("AdminPanel createAdmin: modifyGroup " + e.toString()); + throw new IOException(e.toString()); + } + } + + private void submitRequest(String ca_hostname, int ca_port, HttpServletRequest request, + HttpServletResponse response, Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + + String profileId = HttpInput.getID(request, "profileId"); + if (profileId == null) { + try { + profileId = config.getString("preop.admincert.profile", "caAdminCert"); + } catch (Exception e) { + } + } + + String cert_request_type = HttpInput.getID(request, "cert_request_type"); + String cert_request = HttpInput.getCertRequest(request, "cert_request"); + cert_request = URLEncoder.encode(cert_request, "UTF-8"); + String session_id = CMS.getConfigSDSessionId(); + String subjectDN = HttpInput.getString(request, "subject"); + + String content = + "profileId=" + + profileId + "&cert_request_type=" + cert_request_type + "&cert_request=" + cert_request + + "&xmlOutput=true&sessionID=" + session_id + "&subject=" + subjectDN; + + HttpClient httpclient = new HttpClient(); + String c = null; + + try { + JssSSLSocketFactory factory = new JssSSLSocketFactory(); + + httpclient = new HttpClient(factory); + httpclient.connect(ca_hostname, ca_port); + HttpRequest httprequest = new HttpRequest(); + httprequest.setMethod(HttpRequest.POST); + httprequest.setURI("/ca/ee/ca/profileSubmit"); + httprequest.setHeader("user-agent", "HTTPTool/1.0"); + + httprequest.setHeader("content-length", "" + content.length()); + httprequest.setHeader("content-type", + "application/x-www-form-urlencoded"); + httprequest.setContent(content); + HttpResponse httpresponse = httpclient.send(httprequest); + + c = httpresponse.getContent(); + CMS.debug("AdminPanel submitRequest: content=" + c); + + // retrieve the request Id ad admin certificate + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream( + c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("AdminPanel::submitRequest() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + String status = parser.getValue("Status"); + + CMS.debug("AdminPanel update: status=" + status); + if (status.equals("2")) { + //relogin to the security domain + reloginSecurityDomain(response); + return; + } else if (!status.equals("0")) { + String error = parser.getValue("Error"); + + context.put("errorString", error); + throw new IOException(error); + } + + IConfigStore cs = CMS.getConfigStore(); + String id = parser.getValue("Id"); + + cs.putString("preop.admincert.requestId.0", id); + String serial = parser.getValue("serialno"); + + cs.putString("preop.admincert.serialno.0", serial); + String b64 = parser.getValue("b64"); + String instanceRoot = cs.getString("instanceRoot", ""); + String dir = instanceRoot + File.separator + "conf" + + File.separator + "admin.b64"; + + cs.putString("preop.admincert.b64", dir); + PrintStream ps = new PrintStream(new FileOutputStream(dir)); + + ps.println(b64); + ps.flush(); + ps.close(); + } catch (IOException ee) { + context.put("errorString", ee.toString()); + throw ee; + } catch (Exception ee) { + context.put("errorString", ee.toString()); + throw new IOException(ee.toString()); + } + } + } catch (Exception e) { + CMS.debug("AdminPanel submitRequest: " + e.toString()); + } + } + + private void createAdminCertificate(HttpServletRequest request, + HttpServletResponse response, Context context) throws IOException { + String cert_request = HttpInput.getCertRequest(request, "cert_request"); + + String cert_request_type = HttpInput.getID(request, "cert_request_type"); + IConfigStore cs = CMS.getConfigStore(); + + if (cs == null) { + CMS.debug("AdminPanel::createAdminCertificate() - cs is null!"); + throw new IOException("cs is null"); + } + + String subject = ""; + X509Key x509key = null; + if (cert_request_type.equals("crmf")) { + try { + byte[] b = CMS.AtoB(cert_request); + SEQUENCE crmfMsgs = CryptoUtil.parseCRMFMsgs(b); + subject = CryptoUtil.getSubjectName(crmfMsgs); + x509key = CryptoUtil.getX509KeyFromCRMFMsgs(crmfMsgs); + } catch (Exception e) { + CMS.debug( + "AdminPanel createAdminCertificate: Exception=" + + e.toString()); + } + // this request is from IE. The VBScript has problem of generating + // certificate request if the subject name has E and UID components. + // For now, we always hardcoded the subject DN to be cn=NAME in + // the IE browser. + } else if (cert_request_type.equals("pkcs10")) { + try { + byte[] b = CMS.AtoB(cert_request); + PKCS10 pkcs10 = new PKCS10(b); + subject = request.getParameter("subject"); + x509key = pkcs10.getSubjectPublicKeyInfo(); + } catch (Exception e) { + CMS.debug("AdminPanel createAdminCertificate: Exception=" + + e.toString()); + } + } + + if (x509key == null) { + CMS.debug("AdminPanel::createAdminCertificate() - x509key is null!"); + throw new IOException("x509key is null"); + } + + try { + cs.putString(PCERT_PREFIX + CERT_TAG + ".dn", subject); + String caType = cs.getString(PCERT_PREFIX + CERT_TAG + ".type", "local"); + X509CertImpl impl = CertUtil.createLocalCert(cs, x509key, + PCERT_PREFIX, CERT_TAG, caType, context); + + // update the locally created request for renewal + CertUtil.updateLocalRequest(cs, CERT_TAG, cert_request, cert_request_type, subject); + + ISubsystem ca = (ISubsystem) CMS.getSubsystem("ca"); + if (ca != null) { + createPKCS7(impl); + } + cs.putString("preop.admincert.serialno.0", + impl.getSerialNumber().toString(16)); + } catch (Exception e) { + CMS.debug("AdminPanel createAdminCertificate: Exception=" + + e.toString()); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + context.put("title", "Administrator"); + context.put("panel", "admin/console/config/adminpanel.vm"); + ISubsystem ca = (ISubsystem) CMS.getSubsystem("ca"); + IConfigStore cs = CMS.getConfigStore(); + String type = ""; + String info = ""; + + try { + type = cs.getString("preop.ca.type", ""); + } catch (Exception e) { + } + if (ca == null && type.equals("otherca")) { + info = + "Since you do not join the Redhat CA network, the administrator's certificate will not be generated automatically."; + } + context.put("info", info); + context.put("admin_email", request.getParameter("email")); + context.put("admin_name", request.getParameter("name")); + context.put("admin_pwd", ""); + context.put("admin_pwd_again", ""); + context.put("admin_uid", request.getParameter("uid")); + } + + public boolean shouldSkip() { + try { + IConfigStore c = CMS.getConfigStore(); + String s = c.getString("preop.subsystem.select", null); + if (s != null && s.equals("clone")) { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + private void createPKCS7(X509CertImpl cert) { + try { + IConfigStore cs = CMS.getConfigStore(); + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem("ca"); + CertificateChain cachain = ca.getCACertChain(); + X509Certificate[] cacerts = cachain.getChain(); + X509CertImpl[] userChain = new X509CertImpl[cacerts.length + 1]; + int m = 1, n = 0; + + for (; n < cacerts.length; m++, n++) { + userChain[m] = (X509CertImpl) cacerts[n]; + } + + userChain[0] = cert; + PKCS7 p7 = new PKCS7(new AlgorithmId[0], + new ContentInfo(new byte[0]), userChain, new SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + p7.encodeSignedData(bos); + byte[] p7Bytes = bos.toByteArray(); + String p7Str = CMS.BtoA(p7Bytes); + cs.putString("preop.admincert.pkcs7", CryptoUtil.normalizeCertStr(p7Str)); + } catch (Exception e) { + CMS.debug("AdminPanel createPKCS7: Failed to create pkcs7 file. Exception: " + e.toString()); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/AgentAuthenticatePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/AgentAuthenticatePanel.java new file mode 100644 index 000000000..c1e6bffd1 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/AgentAuthenticatePanel.java @@ -0,0 +1,229 @@ +// --- 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.csadmin; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class AgentAuthenticatePanel extends WizardPanelBase { + + public AgentAuthenticatePanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Agent Authentication"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Agent Authentication"); + setId(id); + } + + public boolean isSubPanel() { + return true; + } + + /** + * Should we skip this panel for the configuration. + */ + public boolean shouldSkip() { + CMS.debug("DisplayCertChainPanel: should skip"); + + IConfigStore cs = CMS.getConfigStore(); + // if we are root, no need to get the certificate chain. + + try { + String select = cs.getString("securitydomain.select", ""); + if (select.equals("new")) { + return true; + } + + String catype = cs.getString("preop.ca.type", ""); + if (catype.equals("otherca")) + return true; + } catch (EBaseException e) { + } + + return false; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.ca.agent.uid", ""); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.ca.agent.uid", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Agent Authentication"); + IConfigStore config = CMS.getConfigStore(); + + if (isPanelDone()) { + + try { + String s = config.getString("preop.ca.agent.uid", ""); + String type = config.getString("preop.hierarchy.select", ""); + if (type.equals("root")) + context.put("uid", ""); + else + context.put("uid", s); + } catch (Exception e) { + CMS.debug(e.toString()); + } + } else { + context.put("uid", ""); + } + + context.put("password", ""); + context.put("panel", "admin/console/config/agentauthenticatepanel.vm"); + context.put("errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + context.put("panel", "admin/console/config/agentauthenticatepanel.vm"); + context.put("title", "Agent Authentication"); + String type = ""; + String catype = ""; + try { + type = config.getString("preop.hierarchy.select", ""); + catype = config.getString("preop.ca.type", ""); + } catch (Exception e) { + } + + if (type.equals("root")) { + CMS.debug("AgentAuthenticatePanel: This is root, no need for authentication"); + } else if (catype.equals("sdca")) { + CMS.debug("AgentAuthenticatePanel: This is not external CA"); + String uid = HttpInput.getUID(request, "uid"); + if (uid == null) { + context.put("errorString", "Uid is empty"); + throw new IOException("Uid is empty"); + } + context.put("uid", uid); + String pwd = HttpInput.getPassword(request, "__password"); + config.putString("preop.ca.agent.uid", uid); + config.putString("preop.ca.agent.pwd", pwd); + + /* + String host = ""; + int httpsport = -1; + + try { + host = config.getString("preop.ca.hostname"); + } catch (Exception e) { + CMS.debug("AgentAuthenticatePanel update: " + e.toString()); + context.put("errorString", "Missing hostname"); + throw new IOException("Missing hostname"); + } + + try { + httpsport = config.getInteger("preop.ca.httpsport"); + } catch (Exception e) { + CMS.debug("AgentAuthenticatePanel update: " + e.toString()); + context.put("errorString", "Missing port"); + throw new IOException("Missing port"); + } + + // Bugzilla Bug #583825 - CC: Obsolete servlets to be removed from + // web.xml as part of CC interface review + boolean authenticated = authenticate(host, httpsport, true, + "/ca/ee/ca/checkIdentity", "uid="+uid+"&pwd="+pwd); + + if (!authenticated) { + context.put("errorString", "Wrong user id or password"); + throw new IOException("Wrong user id or password"); + } + */ + + try { + config.commit(false); + } catch (EBaseException e) { + } + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("password", ""); + context.put("title", "Agent Authentication"); + context.put("panel", "admin/console/config/agentauthenticatepanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java new file mode 100644 index 000000000..6700b9312 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java @@ -0,0 +1,192 @@ +// --- 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.csadmin; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class AuthenticatePanel extends WizardPanelBase { + + public AuthenticatePanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Authentication"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Authentication"); + setId(id); + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.ca.agent.uid", ""); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.ca.agent.uid", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Authentication"); + IConfigStore config = CMS.getConfigStore(); + + if (isPanelDone()) { + + try { + String s = config.getString("preop.ca.agent.uid", ""); + String type = config.getString("preop.hierarchy.select", ""); + if (type.equals("root")) + context.put("uid", ""); + else + context.put("uid", s); + } catch (Exception e) { + CMS.debug(e.toString()); + } + } else { + context.put("uid", ""); + } + + context.put("password", ""); + context.put("panel", "admin/console/config/authenticatepanel.vm"); + context.put("errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + String type = ""; + String catype = ""; + try { + type = config.getString("preop.hierarchy.select", ""); + catype = config.getString("preop.ca.type", ""); + } catch (Exception e) { + } + + if (type.equals("root")) { + CMS.debug("AuthenticatePanel: This is root, no need for authentication"); + } else if (catype.equals("sdca")) { + CMS.debug("AuthenticatePanel: This is not external CA"); + String uid = HttpInput.getUID(request, "uid"); + if (uid == null) { + context.put("errorString", "Uid is empty"); + throw new IOException("Uid is empty"); + } + context.put("uid", uid); + String pwd = HttpInput.getPassword(request, "__password"); + config.putString("preop.ca.agent.uid", uid); + config.putString("preop.ca.agent.pwd", pwd); + String host = ""; + int httpsport = -1; + try { + host = config.getString("preop.ca.hostname"); + } catch (Exception e) { + CMS.debug("AuthenticatePanel update: " + e.toString()); + context.put("errorString", "Missing hostname"); + throw new IOException("Missing hostname"); + } + + try { + httpsport = config.getInteger("preop.ca.httpsport"); + } catch (Exception e) { + CMS.debug("AuthenticatePanel update: " + e.toString()); + context.put("errorString", "Missing port"); + throw new IOException("Missing port"); + } + + boolean authenticated = authenticate(host, httpsport, true, + "/ca/ee/ca/configSubsystem", "uid=" + uid + "&pwd=" + pwd); + + if (!authenticated) { + context.put("errorString", "Wrong user id or password"); + throw new IOException("Wrong user id or password"); + } + + try { + config.commit(false); + } catch (EBaseException e) { + } + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("password", ""); + context.put("panel", "admin/console/config/authenticatepanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java new file mode 100644 index 000000000..d216a9212 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java @@ -0,0 +1,450 @@ +// --- 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.csadmin; + +import java.io.ByteArrayOutputStream; +import java.io.CharConversionException; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateEncodingException; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.ASN1Value; +import org.mozilla.jss.asn1.BMPString; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.crypto.Cipher; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.EncryptionAlgorithm; +import org.mozilla.jss.crypto.IVParameterSpec; +import org.mozilla.jss.crypto.KeyGenAlgorithm; +import org.mozilla.jss.crypto.KeyGenerator; +import org.mozilla.jss.crypto.KeyWrapAlgorithm; +import org.mozilla.jss.crypto.KeyWrapper; +import org.mozilla.jss.crypto.PBEAlgorithm; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.SymmetricKey; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.pkcs12.AuthenticatedSafes; +import org.mozilla.jss.pkcs12.CertBag; +import org.mozilla.jss.pkcs12.PFX; +import org.mozilla.jss.pkcs12.PasswordConverter; +import org.mozilla.jss.pkcs12.SafeBag; +import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; +import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; +import org.mozilla.jss.util.Password; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class BackupKeyCertPanel extends WizardPanelBase { + + public BackupKeyCertPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Export Keys and Certificates"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Export Keys and Certificates"); + setId(id); + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + /* clean up if necessary */ + try { + @SuppressWarnings("unused") + boolean done = cs.getBoolean("preop.backupkeycert.done"); // check for errors + cs.putBoolean("preop.backupkeycert.done", false); + cs.commit(false); + } catch (Exception e) { + } + } + + public boolean shouldSkip() { + IConfigStore cs = CMS.getConfigStore(); + + try { + String s = cs.getString("preop.module.token", ""); + if (s.equals("Internal Key Storage Token")) + return false; + } catch (Exception e) { + } + + return true; + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.backupkeycert.done", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Export Keys and Certificates"); + IConfigStore config = CMS.getConfigStore(); + + if (isPanelDone()) { + try { + boolean enable = config.getBoolean("preop.backupkeys.enable"); + if (enable) { + context.put("dobackup", "checked"); + context.put("nobackup", ""); + } else { + context.put("dobackup", ""); + context.put("nobackup", "checked"); + } + } catch (Exception e) { + } + } else { + context.put("dobackup", ""); + context.put("nobackup", "checked"); + } + + context.put("panel", "admin/console/config/backupkeycertpanel.vm"); + context.put("pwd", ""); + context.put("pwdagain", ""); + context.put("errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, Context context) throws IOException { + String select = HttpInput.getID(request, "choice"); + if (select.equals("backupkey")) { + String pwd = request.getParameter("__pwd"); + String pwdAgain = request.getParameter("__pwdagain"); + if (pwd == null || pwdAgain == null || pwd.equals("") || pwdAgain.equals("")) { + CMS.debug("BackupKeyCertPanel validate: Password is null"); + context.put("updateStatus", "validate-failure"); + throw new IOException("PK12 password is empty."); + } + + if (!pwd.equals(pwdAgain)) { + CMS.debug("BackupKeyCertPanel validate: Password and password again are not the same."); + context.put("updateStatus", "validate-failure"); + throw new IOException("PK12 password is different from the PK12 password again."); + } + } + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + + String select = HttpInput.getID(request, "choice"); + if (select.equals("backupkey")) { + CMS.debug("BackupKeyCertPanel update: backup"); + config.putBoolean("preop.backupkeys.enable", true); + backupKeysCerts(request); + } else { + CMS.debug("BackupKeyCertPanel update: no backup"); + config.putBoolean("preop.backupkeys.enable", false); + } + + config.putBoolean("preop.backupkeycert.done", true); + try { + config.commit(false); + } catch (EBaseException e) { + } + context.put("updateStatus", "success"); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String select = ""; + try { + select = HttpInput.getID(request, "choice"); + } catch (Exception e) { + } + + if (select.equals("backupkey")) { + context.put("dobackup", "checked"); + context.put("nobackup", ""); + } else { + context.put("dobackup", ""); + context.put("nobackup", "checked"); + } + + context.put("pwd", ""); + context.put("pwdagain", ""); + context.put("title", "Export Keys and Certificates"); + context.put("panel", "admin/console/config/backupkeycertpanel.vm"); + } + + public void backupKeysCerts(HttpServletRequest request) + throws IOException { + CMS.debug("BackupKeyCertPanel backupKeysCerts: start"); + IConfigStore cs = CMS.getConfigStore(); + String certlist = ""; + try { + certlist = cs.getString("preop.cert.list"); + } catch (Exception e) { + } + + StringTokenizer st = new StringTokenizer(certlist, ","); + CryptoManager cm = null; + try { + cm = CryptoManager.getInstance(); + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel::backupKeysCerts() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String pwd = request.getParameter("__pwd"); + Password pass = new org.mozilla.jss.util.Password(pwd.toCharArray()); + SEQUENCE encSafeContents = new SEQUENCE(); + SEQUENCE safeContents = new SEQUENCE(); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + if (t.equals("sslserver")) + continue; + String nickname = ""; + String modname = ""; + try { + nickname = cs.getString("preop.cert." + t + ".nickname"); + modname = cs.getString("preop.module.token"); + } catch (Exception e) { + } + if (!modname.equals("Internal Key Storage Token")) + nickname = modname + ":" + nickname; + + X509Certificate x509cert = null; + byte localKeyId[] = null; + try { + x509cert = cm.findCertByNickname(nickname); + localKeyId = addCertBag(x509cert, nickname, safeContents); + } catch (IOException e) { + throw e; + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel: Exception=" + e.toString()); + throw new IOException("Failed to create pkcs12 file."); + } + + try { + PrivateKey pkey = cm.findPrivKeyByCert(x509cert); + addKeyBag(pkey, x509cert, pass, localKeyId, encSafeContents); + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel: Exception=" + e.toString()); + throw new IOException("Failed to create pkcs12 file."); + } + } //while loop + + X509Certificate[] cacerts = cm.getCACerts(); + + for (int i = 0; i < cacerts.length; i++) { + //String nickname = cacerts[i].getSubjectDN().toString(); + String nickname = null; + try { + addCertBag(cacerts[i], nickname, safeContents); + } catch (IOException e) { + throw e; + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel backKeysCerts: Exception=" + e.toString()); + throw new IOException("Failed to create pkcs12 file."); + } + } + + try { + AuthenticatedSafes authSafes = new AuthenticatedSafes(); + authSafes.addSafeContents(safeContents); + authSafes.addSafeContents(encSafeContents); + PFX pfx = new PFX(authSafes); + pfx.computeMacData(pass, null, 5); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + pfx.encode(bos); + byte[] output = bos.toByteArray(); + cs.putString("preop.pkcs12", CryptoUtil.byte2string(output)); + pass.clear(); + cs.commit(false); + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel backupKeysCerts: Exception=" + e.toString()); + } + } + + private void addKeyBag(PrivateKey pkey, X509Certificate x509cert, + Password pass, byte[] localKeyId, SEQUENCE safeContents) + throws IOException { + try { + PasswordConverter passConverter = new PasswordConverter(); + + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + byte salt[] = random.generateSeed(4); // 4 bytes salt + byte[] priData = getEncodedKey(pkey); + + PrivateKeyInfo pki = (PrivateKeyInfo) + ASN1Util.decode(PrivateKeyInfo.getTemplate(), priData); + ASN1Value key = EncryptedPrivateKeyInfo.createPBE( + PBEAlgorithm.PBE_SHA1_DES3_CBC, + pass, salt, 1, passConverter, pki); + SET keyAttrs = createBagAttrs( + x509cert.getSubjectDN().toString(), localKeyId); + SafeBag keyBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, + key, keyAttrs); + safeContents.addElement(keyBag); + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel getKeyBag: Exception=" + e.toString()); + throw new IOException("Failed to create pk12 file."); + } + } + + private byte[] addCertBag(X509Certificate x509cert, String nickname, + SEQUENCE safeContents) throws IOException { + byte[] localKeyId = null; + try { + ASN1Value cert = new OCTET_STRING(x509cert.getEncoded()); + localKeyId = createLocalKeyId(x509cert); + SET certAttrs = null; + if (nickname != null) + certAttrs = createBagAttrs(nickname, localKeyId); + SafeBag certBag = new SafeBag(SafeBag.CERT_BAG, + new CertBag(CertBag.X509_CERT_TYPE, cert), certAttrs); + safeContents.addElement(certBag); + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel addCertBag: " + e.toString()); + throw new IOException("Failed to create pk12 file."); + } + + return localKeyId; + } + + private byte[] getEncodedKey(PrivateKey pkey) { + try { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken token = cm.getInternalKeyStorageToken(); + KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); + SymmetricKey sk = kg.generate(); + KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); + byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; + IVParameterSpec param = new IVParameterSpec(iv); + wrapper.initWrap(sk, param); + byte[] enckey = wrapper.wrap(pkey); + Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); + c.initDecrypt(sk, param); + byte[] recovered = c.doFinal(enckey); + return recovered; + } catch (Exception e) { + CMS.debug("BackupKeyCertPanel getEncodedKey: Exception=" + e.toString()); + } + + return null; + } + + private byte[] createLocalKeyId(X509Certificate cert) + throws IOException { + try { + // SHA1 hash of the X509Cert der encoding + byte certDer[] = cert.getEncoded(); + + MessageDigest md = MessageDigest.getInstance("SHA"); + + md.update(certDer); + return md.digest(); + } catch (CertificateEncodingException e) { + CMS.debug("BackupKeyCertPanel createLocalKeyId: Exception: " + e.toString()); + throw new IOException("Failed to encode certificate."); + } catch (NoSuchAlgorithmException e) { + CMS.debug("BackupKeyCertPanel createLocalKeyId: Exception: " + e.toString()); + throw new IOException("No such algorithm supported."); + } + } + + private SET createBagAttrs(String nickName, byte localKeyId[]) + throws IOException { + try { + SET attrs = new SET(); + SEQUENCE nickNameAttr = new SEQUENCE(); + + nickNameAttr.addElement(SafeBag.FRIENDLY_NAME); + SET nickNameSet = new SET(); + + nickNameSet.addElement(new BMPString(nickName)); + nickNameAttr.addElement(nickNameSet); + attrs.addElement(nickNameAttr); + SEQUENCE localKeyAttr = new SEQUENCE(); + + localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID); + SET localKeySet = new SET(); + + localKeySet.addElement(new OCTET_STRING(localKeyId)); + localKeyAttr.addElement(localKeySet); + attrs.addElement(localKeyAttr); + return attrs; + } catch (CharConversionException e) { + CMS.debug("BackupKeyCertPanel createBagAttrs: Exception=" + e.toString()); + throw new IOException("Failed to create PKCS12 file."); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/BaseServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/BaseServlet.java new file mode 100644 index 000000000..9e800b9cc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/BaseServlet.java @@ -0,0 +1,121 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; +import org.apache.velocity.servlet.VelocityServlet; + +import com.netscape.certsrv.apps.CMS; + +public class BaseServlet extends VelocityServlet { + + /** + * + */ + private static final long serialVersionUID = 3169697149104780149L; + + /** + * Returns usage of this servlet. + */ + public String getUsage() { + return null; + } + + public boolean authenticate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String pin = (String) request.getSession().getAttribute("pin"); + + if (pin == null) { + try { + response.sendRedirect("login"); + } catch (IOException e) { + } + return false; + } + return true; + } + + public void outputHttpParameters(HttpServletRequest httpReq) { + CMS.debug("BaseServlet:service() uri = " + httpReq.getRequestURI()); + @SuppressWarnings("unchecked") + Enumeration<String> paramNames = httpReq.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String pn = 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 (pn.startsWith("__") || + pn.endsWith("password") || + pn.endsWith("passwd") || + pn.endsWith("pwd") || + pn.equalsIgnoreCase("admin_password_again") || + pn.equalsIgnoreCase("directoryManagerPwd") || + pn.equalsIgnoreCase("bindpassword") || + pn.equalsIgnoreCase("bindpwd") || + pn.equalsIgnoreCase("passwd") || + pn.equalsIgnoreCase("password") || + pn.equalsIgnoreCase("pin") || + pn.equalsIgnoreCase("pwd") || + pn.equalsIgnoreCase("pwdagain") || + pn.equalsIgnoreCase("uPasswd")) { + CMS.debug("BaseServlet::service() param name='" + pn + + "' value='(sensitive)'"); + } else { + CMS.debug("BaseServlet::service() param name='" + pn + + "' value='" + httpReq.getParameter(pn) + "'"); + } + } + } + + /** + * Processes request. + */ + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + return null; + } + + public Template handleRequest(HttpServletRequest request, + HttpServletResponse response, + Context context) { + if (CMS.debugOn()) { + outputHttpParameters(request); + } + + /* XXX - authentication */ + if (!authenticate(request, response, context)) { + return null; + } + + /* XXX - authorization */ + + return process(request, response, context); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java new file mode 100644 index 000000000..827f0ce92 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java @@ -0,0 +1,327 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.net.URL; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class CAInfoPanel extends WizardPanelBase { + + public CAInfoPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("CA Information"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("CA Information"); + setId(id); + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.ca.type", ""); + } + + public boolean shouldSkip() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.subsystem.select", ""); + if (s.equals("clone")) + return true; + } catch (Exception e) { + } + return false; + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.ca.type", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (Exception e) { + } + + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("CAInfoPanel: display"); + + IConfigStore cs = CMS.getConfigStore(); + String hostname = ""; + String httpport = ""; + String httpsport = ""; + + if (isPanelDone()) { + String type = "sdca"; + + try { + type = cs.getString("preop.ca.type"); + } catch (Exception e) { + CMS.debug("CAInfoPanel exception: " + e.toString()); + return; + } + + try { + hostname = cs.getString("preop.ca.hostname"); + } catch (Exception e) { + } + + try { + httpport = cs.getString("preop.ca.httpport"); + } catch (Exception e) { + } + + try { + httpsport = cs.getString("preop.ca.httpsport"); + } catch (Exception e) { + } + + if (type.equals("sdca")) { + context.put("check_sdca", "checked"); + context.put("check_otherca", ""); + } else if (type.equals("otherca")) { + context.put("check_sdca", ""); + context.put("check_otherca", "checked"); + } + } else { + context.put("check_sdca", "checked"); + context.put("check_otherca", ""); + } + + String cstype = "CA"; + String portType = "SecurePort"; + + /* + try { + cstype = cs.getString("cs.type", ""); + } catch (EBaseException e) {} + */ + + CMS.debug("CAInfoPanel: Ready to get url"); + Vector<String> v = getUrlListFromSecurityDomain(cs, cstype, portType); + v.addElement("External CA"); + StringBuffer list = new StringBuffer(); + int size = v.size(); + + for (int i = 0; i < size; i++) { + if (i == size - 1) { + list.append(v.elementAt(i)); + } else { + list.append(v.elementAt(i)); + list.append(","); + } + } + + try { + cs.putString("preop.ca.list", list.toString()); + cs.commit(false); + } catch (Exception e) { + } + + context.put("urls", v); + + context.put("sdcaHostname", hostname); + context.put("sdcaHttpPort", httpport); + context.put("sdcaHttpsPort", httpsport); + context.put("title", "CA Information"); + context.put("panel", "admin/console/config/cainfopanel.vm"); + context.put("errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + + /* + String select = request.getParameter("choice"); + if (select == null) { + CMS.debug("CAInfoPanel: choice not found"); + throw new IOException("choice not found"); + } + */ + IConfigStore config = CMS.getConfigStore(); + + try { + String subsystemselect = config.getString("preop.subsystem.select", ""); + if (subsystemselect.equals("clone")) + return; + } catch (Exception e) { + } + + String select = null; + String index = request.getParameter("urls"); + String url = ""; + if (index.startsWith("http")) { + // user may submit url directlry + url = index; + } else { + try { + int x = Integer.parseInt(index); + String list = config.getString("preop.ca.list", ""); + StringTokenizer tokenizer = new StringTokenizer(list, ","); + int counter = 0; + + while (tokenizer.hasMoreTokens()) { + url = tokenizer.nextToken(); + if (counter == x) { + break; + } + counter++; + } + } catch (Exception e) { + } + } + + URL urlx = null; + + if (url.equals("External CA")) { + select = "otherca"; + config.putString("preop.ca.pkcs7", ""); + config.putInteger("preop.ca.certchain.size", 0); + } else { + select = "sdca"; + + // parse URL (CA1 - https://...) + url = url.substring(url.indexOf("https")); + urlx = new URL(url); + } + + ISubsystem subsystem = CMS.getSubsystem(ICertificateAuthority.ID); + + if (select.equals("sdca")) { + config.putString("preop.ca.type", "sdca"); + CMS.debug("CAInfoPanel update: this is the CA in the security domain."); + context.put("check_sdca", "checked"); + sdca(request, context, urlx.getHost(), + Integer.toString(urlx.getPort())); + if (subsystem != null) { + config.putString(PCERT_PREFIX + "signing.type", "remote"); + config.putString(PCERT_PREFIX + "signing.profile", + "caInstallCACert"); + } + } else if (select.equals("otherca")) { + config.putString("preop.ca.type", "otherca"); + context.put("check_otherca", "checked"); + if (subsystem != null) { + config.putString(PCERT_PREFIX + "signing.type", "remote"); + } + CMS.debug("CAInfoPanel update: this is the other CA."); + } + + try { + config.commit(false); + } catch (Exception e) { + } + } + + private void sdca(HttpServletRequest request, Context context, String hostname, String httpsPortStr) + throws IOException { + CMS.debug("CAInfoPanel update: this is the CA in the security domain."); + IConfigStore config = CMS.getConfigStore(); + + context.put("sdcaHostname", hostname); + context.put("sdcaHttpsPort", httpsPortStr); + + if (hostname == null || hostname.length() == 0) { + context.put("errorString", "Hostname is null"); + throw new IOException("Hostname is null"); + } + + int httpsport = -1; + + try { + httpsport = Integer.parseInt(httpsPortStr); + } catch (Exception e) { + CMS.debug( + "CAInfoPanel update: Https port is not valid. Exception: " + + e.toString()); + throw new IOException("Http Port is not valid."); + } + + config.putString("preop.ca.hostname", hostname); + config.putString("preop.ca.httpsport", httpsPortStr); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + updateCertChainUsingSecureEEPort(config, "ca", hostname, + httpsport, true, context, + certApprovalCallback); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + /* This should never be called */ + context.put("title", "CA Information"); + context.put("panel", "admin/console/config/cainfopanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/Cert.java b/base/common/src/com/netscape/cms/servlet/csadmin/Cert.java new file mode 100644 index 000000000..0aedded83 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/Cert.java @@ -0,0 +1,179 @@ +// --- 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.csadmin; + +public class Cert { + private String mNickname = ""; + private String mTokenname = ""; + private String mRequest = ""; + private String mCert = ""; + private String mType = ""; // "selfsign," "local," or "remote" + private String mDN = ""; + private String mCertTag = ""; + private String mCertpp = ""; + private String mUserFriendlyName = ""; + private String mKeyOption = ""; + private String mCustomKeysize = ""; + private String mCustomCurvename = ""; + private boolean mEnable = true; + private boolean mSigningRequired = false; + private String mSubsystem = ""; + + public Cert(String tokenName, String nickName, String certTag) { + mTokenname = tokenName; + mNickname = nickName; + mCertTag = certTag; + } + + public void setEnable(boolean enable) { + mEnable = enable; + } + + public boolean isEnable() { + return mEnable; + } + + public void setSigningRequired(boolean required) { + mSigningRequired = required; + } + + public boolean isSigningRequired() { + return mSigningRequired; + } + + public void setNickname(String s) { + mNickname = s; + } + + public String getNickname() { + return mNickname; + } + + public void setSubsystem(String s) { + mSubsystem = s; + } + + public String getSubsystem() { + return mSubsystem; + } + + public String getUserFriendlyName() { + return mUserFriendlyName; + } + + public void setUserFriendlyName(String name) { + mUserFriendlyName = name; + } + + public String getTokenname() { + return mTokenname; + } + + public String getRequest() { + return mRequest; + } + + public void setRequest(String req) { + mRequest = req; + } + + public String getEscapedCert() { + return escapeForHTML(mCert); + } + + public String getCert() { + return mCert; + } + + public void setCert(String cert) { + mCert = cert; + } + + public String getType() { + return mType; + } + + public void setType(String type) { + mType = type; + } + + public String escapeForHTML(String s) { + s = s.replaceAll("\"", """); + return s; + } + + public String getEscapedDN() { + // Need to escape " + return escapeForHTML(mDN); + } + + public String getDN() { + return mDN; + } + + public void setDN(String dn) { + mDN = dn; + } + + public String getCertTag() { + return mCertTag; + } + + public String getEscapedCertpp() { + return escapeForHTML(mCertpp); + } + + public String getCertpp() { + return mCertpp; + } + + public void setCertpp(String pp) { + mCertpp = pp; + } + + public String getKeyOption() { + return mKeyOption; + } + + /* + * "default" or "custom" + */ + public void setKeyOption(String option) { + mKeyOption = option; + } + + public boolean useDefaultKey() { + return (mKeyOption.equals("default")); + } + + public String getCustomKeysize() { + return mCustomKeysize; + } + + public void setCustomKeysize(String size) { + mCustomKeysize = size; + } + + public String getCustomCurvename() { + return mCustomCurvename; + } + + public void setCustomCurvename(String curve) { + mCustomCurvename = curve; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CertPrettyPrintPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/CertPrettyPrintPanel.java new file mode 100644 index 000000000..9c4315c05 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/CertPrettyPrintPanel.java @@ -0,0 +1,210 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.util.CertPrettyPrint; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class CertPrettyPrintPanel extends WizardPanelBase { + private Vector<Cert> mCerts = null; + + public CertPrettyPrintPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Certificates"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Certificates"); + setId(id); + } + + public PropertySet getUsage() { + // expects no input from client + PropertySet set = new PropertySet(); + + return set; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putBoolean("preop.CertPrettyPrintPanel.done", false); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + boolean s = cs.getBoolean("preop.CertPrettyPrintPanel.done", + false); + + if (s != true) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public void getCert(HttpServletRequest req, IConfigStore config, + Context context, String certTag, Cert cert) { + CMS.debug("CertPrettyPrintPanel: in getCert()"); + try { + // String cert = config.getString(CONF_CA_CERT); + String subsystem = config.getString(PCERT_PREFIX + certTag + ".subsystem"); + String certs = config.getString(subsystem + "." + certTag + ".cert"); + byte[] certb = CryptoUtil.base64Decode(certs); + + if (cert != null) { + CertPrettyPrint pp = new CertPrettyPrint(certb); + cert.setCertpp(pp.toString(Locale.getDefault())); + String certf = CryptoUtil.certFormat(certs); + + // String canickname = config.getString(CONF_CA_CERTNICKNAME); + // context.put("cert", certf); + // context.put("nickname", nickname); + cert.setCert(certf); + } + } catch (Exception e) { + CMS.debug("CertPrettyPrintPanel:getCert" + e.toString()); + } // try + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + CMS.debug("CertPrettyPrintPanel: display()"); + context.put("title", "Certificates Pretty Print"); + + try { + mCerts = new Vector<Cert>(); + + IConfigStore config = CMS.getConfigStore(); + + String certTags = config.getString("preop.cert.list"); + StringTokenizer st = new StringTokenizer(certTags, ","); + + while (st.hasMoreTokens()) { + String certTag = st.nextToken(); + + try { + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + + String nickname = config.getString( + subsystem + "." + certTag + ".nickname"); + String tokenname = config.getString( + subsystem + "." + certTag + ".tokenname"); + Cert c = new Cert(tokenname, nickname, certTag); + + String type = config.getString( + PCERT_PREFIX + certTag + ".type"); + + c.setType(type); + getCert(request, config, context, certTag, c); + + mCerts.addElement(c); + } catch (Exception e) { + CMS.debug( + "CertPrettyPrintPanel: display() certTag " + certTag + + " Exception caught: " + e.toString()); + } + } + } catch (Exception e) { + CMS.debug( + "CertPrettyPrintPanel:display() Exception caught: " + + e.toString()); + System.err.println("Exception caught: " + e.toString()); + + } // try + + context.put("ppcerts", mCerts); + context.put("status", "display"); + // context.put("status_token", "None"); + context.put("panel", "admin/console/config/certprettyprintpanel.vm"); + + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + CMS.debug("CertPrettyPrintPanel: in update()"); + IConfigStore config = CMS.getConfigStore(); + config.putBoolean("preop.CertPrettyPrintPanel.done", true); + try { + config.commit(false); + } catch (EBaseException e) { + CMS.debug( + "CertPrettyPrintPanel: update() Exception caught at config commit: " + + e.toString()); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Certificates Pretty Print"); + context.put("panel", "admin/console/config/certprettyprintpanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java new file mode 100644 index 000000000..20ddf9f2d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java @@ -0,0 +1,757 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.Principal; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.pkcs.PKCS10; +import netscape.security.util.CertPrettyPrint; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.InternalCertificate; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.X509Certificate; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class CertRequestPanel extends WizardPanelBase { + private Vector<Cert> mCerts = null; + private WizardServlet mServlet = null; + + public CertRequestPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Requests & Certificates"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Requests and Certificates"); + mServlet = servlet; + setId(id); + } + + // XXX how do you do this? There could be multiple certs. + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + Descriptor certDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameters */ + null); + + set.add("cert", certDesc); + + return set; + } + + /** + * Show "Apply" button on frame? + */ + public boolean showApplyButton() { + if (isPanelDone()) + return false; + else + return true; + } + + private boolean findCertificate(String tokenname, String nickname) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + CryptoManager cm = null; + try { + cm = CryptoManager.getInstance(); + } catch (Exception e) { + } + + String fullnickname = nickname; + + boolean hardware = false; + if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) { + hardware = true; + fullnickname = tokenname + ":" + nickname; + } + + try { + X509Certificate cert = cm.findCertByNickname(fullnickname); + if (cert == null) + return false; + try { + @SuppressWarnings("unused") + boolean done = cs.getBoolean("preop.CertRequestPanel.done"); // check for errors + return true; + } catch (Exception ee) { + if (hardware) { + CMS.debug("CertRequestPanel findCertificate: The certificate with the same nickname: " + + fullnickname + " has been found on HSM. Please remove it before proceeding."); + throw new IOException("The certificate with the same nickname: " + + fullnickname + " has been found on HSM. Please remove it before proceeding."); + } + return true; + } + } catch (IOException e) { + CMS.debug("CertRequestPanel findCertificate: throw exception:" + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("CertRequestPanel findCertificate: Exception=" + e.toString()); + return false; + } + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + String list = ""; + String tokenname = ""; + try { + list = cs.getString("preop.cert.list", ""); + tokenname = cs.getString("preop.module.token", ""); + } catch (Exception e) { + } + + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem( + ICertificateAuthority.ID); + + if (ca != null) { + CMS.debug("CertRequestPanel cleanup: get certificate repository"); + BigInteger beginS = null; + BigInteger endS = null; + String beginNum = ""; + String endNum = ""; + try { + beginNum = cs.getString("dbs.beginSerialNumber", ""); + endNum = cs.getString("dbs.endSerialNumber", ""); + if (!beginNum.equals("")) + beginS = new BigInteger(beginNum, 16); + if (!endNum.equals("")) + endS = new BigInteger(endNum, 16); + } catch (Exception e) { + } + + ICertificateRepository cr = ca.getCertificateRepository(); + if (cr != null) { + try { + cr.removeCertRecords(beginS, endS); + } catch (Exception e) { + CMS.debug("CertRequestPanel cleanUp exception in removing all objects: " + e.toString()); + } + + try { + cr.resetSerialNumber(new BigInteger(beginNum, 16)); + } catch (Exception e) { + CMS.debug("CertRequestPanel cleanUp exception in resetting serial number: " + e.toString()); + } + } + } + + StringTokenizer st = new StringTokenizer(list, ","); + String nickname = ""; + boolean enable = false; + while (st.hasMoreTokens()) { + String t = st.nextToken(); + + try { + enable = cs.getBoolean(PCERT_PREFIX + t + ".enable", true); + nickname = cs.getString(PCERT_PREFIX + t + ".nickname", ""); + } catch (Exception e) { + } + + if (!enable) + continue; + + if (t.equals("sslserver")) + continue; + + if (findCertificate(tokenname, nickname)) { + try { + CMS.debug("CertRequestPanel cleanup: deleting certificate (" + nickname + ")."); + deleteCert(tokenname, nickname); + } catch (Exception e) { + CMS.debug("CertRequestPanel cleanup: failed to delete certificate (" + + nickname + "). Exception: " + e.toString()); + } + } + } + + try { + @SuppressWarnings("unused") + boolean done = cs.getBoolean("preop.CertRequestPanel.done"); // check for errors + cs.putBoolean("preop.CertRequestPanel.done", false); + cs.commit(false); + } catch (Exception e) { + } + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + boolean s = cs.getBoolean("preop.CertRequestPanel.done", + false); + + if (s != true) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public void getCert(IConfigStore config, + Context context, String certTag, Cert cert) { + try { + + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + + String certs = config.getString(subsystem + "." + certTag + ".cert", ""); + + if (cert != null) { + String certf = certs; + + CMS.debug( + "CertRequestPanel getCert: certTag=" + certTag + + " cert=" + certs); + //get and set formated cert + if (!certs.startsWith("...")) { + certf = CryptoUtil.certFormat(certs); + } + cert.setCert(certf); + + //get and set cert pretty print + byte[] certb = CryptoUtil.base64Decode(certs); + CertPrettyPrint pp = new CertPrettyPrint(certb); + cert.setCertpp(pp.toString(Locale.getDefault())); + } else { + CMS.debug("CertRequestPanel::getCert() - cert is null!"); + return; + } + String userfriendlyname = config.getString( + PCERT_PREFIX + certTag + ".userfriendlyname"); + + cert.setUserFriendlyName(userfriendlyname); + String type = config.getString(PCERT_PREFIX + certTag + ".type"); + + cert.setType(type); + String dn = config.getString(PCERT_PREFIX + certTag + ".dn"); + + cert.setDN(dn); + } catch (Exception e) { + CMS.debug("CertRequestPanel:getCert" + e.toString()); + } // try + } + + public X509Key getECCX509Key(IConfigStore config, String certTag) + throws Exception { + X509Key pubk = null; + String pubKeyEncoded = config.getString( + PCERT_PREFIX + certTag + ".pubkey.encoded"); + pubk = CryptoUtil.getPublicX509ECCKey(CryptoUtil.string2byte(pubKeyEncoded)); + return pubk; + } + + public X509Key getRSAX509Key(IConfigStore config, String certTag) + throws Exception { + X509Key pubk = null; + + String pubKeyModulus = config.getString( + PCERT_PREFIX + certTag + ".pubkey.modulus"); + String pubKeyPublicExponent = config.getString( + PCERT_PREFIX + certTag + ".pubkey.exponent"); + pubk = CryptoUtil.getPublicX509Key( + CryptoUtil.string2byte(pubKeyModulus), + CryptoUtil.string2byte(pubKeyPublicExponent)); + return pubk; + } + + public void handleCertRequest(IConfigStore config, + Context context, String certTag, Cert cert) { + try { + // get public key + String pubKeyType = config.getString( + PCERT_PREFIX + certTag + ".keytype"); + String algorithm = config.getString( + PCERT_PREFIX + certTag + ".keyalgorithm"); + X509Key pubk = null; + if (pubKeyType.equals("rsa")) { + pubk = getRSAX509Key(config, certTag); + } else if (pubKeyType.equals("ecc")) { + pubk = getECCX509Key(config, certTag); + } else { + CMS.debug("CertRequestPanel::handleCertRequest() - " + + "pubKeyType " + pubKeyType + " is unsupported!"); + return; + } + + CMS.debug("CertRequestPanel: tag=" + certTag); + if (pubk != null) { + CMS.debug("CertRequestPanel: got public key"); + } else { + CMS.debug("CertRequestPanel: error getting public key null"); + return; + } + + // get private key + String privKeyID = config.getString( + PCERT_PREFIX + certTag + ".privkey.id"); + CMS.debug("CertRequestPanel: privKeyID=" + privKeyID); + byte[] keyIDb = CryptoUtil.string2byte(privKeyID); + + PrivateKey privk = CryptoUtil.findPrivateKeyFromID(keyIDb); + + if (privk != null) { + CMS.debug("CertRequestPanel: got private key"); + } else { + CMS.debug("CertRequestPanel: error getting private key null"); + } + + // construct cert request + String caDN = config.getString(PCERT_PREFIX + certTag + ".dn"); + + cert.setDN(caDN); + PKCS10 certReq = CryptoUtil.createCertificationRequest(caDN, pubk, + privk, algorithm); + + CMS.debug("CertRequestPanel: created cert request"); + byte[] certReqb = certReq.toByteArray(); + String certReqs = CryptoUtil.base64Encode(certReqb); + String certReqf = CryptoUtil.reqFormat(certReqs); + + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + config.putString(subsystem + "." + certTag + ".certreq", certReqs); + config.commit(false); + cert.setRequest(certReqf); + } catch (Exception e) { + CMS.debug("CertRequestPanel::handleCertRequest" + e.toString()); + CMS.debug(e); + } // try + + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + CMS.debug("CertRequestPanel: display()"); + context.put("title", "Requests and Certificates"); + + try { + mCerts = new Vector<Cert>(); + + IConfigStore config = CMS.getConfigStore(); + + String certTags = config.getString("preop.cert.list"); + StringTokenizer st = new StringTokenizer(certTags, ","); + + while (st.hasMoreTokens()) { + String certTag = st.nextToken(); + + try { + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + String nickname = config.getString( + subsystem + "." + certTag + ".nickname"); + String tokenname = config.getString( + subsystem + "." + certTag + ".tokenname"); + Cert c = new Cert(tokenname, nickname, certTag); + + handleCertRequest(config, context, certTag, c); + + String type = config.getString( + PCERT_PREFIX + certTag + ".type"); + + c.setType(type); + boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true); + c.setEnable(enable); + getCert(config, context, certTag, c); + + c.setSubsystem(subsystem); + mCerts.addElement(c); + } catch (Exception e) { + CMS.debug( + "CertRequestPanel:display() Exception caught: " + + e.toString() + " for certTag " + certTag); + } + } + } catch (Exception e) { + CMS.debug( + "CertRequestPanel:display() Exception caught: " + + e.toString()); + System.err.println("Exception caught: " + e.toString()); + + } // try + + context.put("reqscerts", mCerts); + context.put("status", "display"); + // context.put("status_token", "None"); + context.put("panel", "admin/console/config/certrequestpanel.vm"); + + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + private boolean findBootstrapServerCert() { + IConfigStore cs = CMS.getConfigStore(); + try { + String instanceID = cs.getString("instanceId", ""); + String nickname = "Server-Cert cert-" + instanceID; + + CryptoManager cm = CryptoManager.getInstance(); + X509Certificate cert = cm.findCertByNickname(nickname); + Principal issuerDN = cert.getIssuerDN(); + Principal subjectDN = cert.getSubjectDN(); + if (issuerDN.equals(subjectDN)) + return true; + } catch (Exception e) { + CMS.debug("CertRequestPanel findBootstrapServerCert Exception=" + e.toString()); + } + + return false; + } + + private void deleteBootstrapServerCert() { + IConfigStore cs = CMS.getConfigStore(); + try { + String instanceID = cs.getString("instanceId", ""); + String nickname = "Server-Cert cert-" + instanceID; + + deleteCert("Internal Key Storage Token", nickname); + } catch (Exception e) { + CMS.debug("CertRequestPanel deleteBootstrapServerCert Exception=" + e.toString()); + } + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + CMS.debug("CertRequestPanel: in update()"); + boolean hasErr = false; + IConfigStore config = CMS.getConfigStore(); + + if (isPanelDone()) { + context.put("updateStatus", "success"); + return; + } + + try { + Enumeration<Cert> c = mCerts.elements(); + + String tokenname = ""; + try { + tokenname = config.getString("preop.module.token", ""); + } catch (Exception e) { + } + + while (c.hasMoreElements()) { + Cert cert = (Cert) c.nextElement(); + String certTag = cert.getCertTag(); + String subsystem = cert.getSubsystem(); + boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true); + if (!enable) + continue; + + if (hasErr) + continue; + + String nickname = cert.getNickname(); + + CMS.debug( + "CertRequestPanel: update() for cert tag " + + cert.getCertTag()); + // String b64 = config.getString(CERT_PREFIX+ certTag +".cert", ""); + String b64 = HttpInput.getCert(request, certTag); + + if (cert.getType().equals("local") + && b64.equals( + "...certificate be generated internally...")) { + + String pubKeyType = config.getString( + PCERT_PREFIX + certTag + ".keytype"); + X509Key x509key = null; + if (pubKeyType.equals("rsa")) { + x509key = getRSAX509Key(config, certTag); + } else if (pubKeyType.equals("ecc")) { + x509key = getECCX509Key(config, certTag); + } + + if (findCertificate(tokenname, nickname)) { + if (!certTag.equals("sslserver")) + continue; + } + X509CertImpl impl = CertUtil.createLocalCert(config, x509key, + PCERT_PREFIX, certTag, cert.getType(), context); + + if (impl != null) { + byte[] certb = impl.getEncoded(); + String certs = CryptoUtil.base64Encode(certb); + + cert.setCert(certs); + config.putString(subsystem + "." + certTag + ".cert", certs); + /* import certificate */ + CMS.debug( + "CertRequestPanel configCert: nickname=" + + nickname); + + try { + if (certTag.equals("sslserver") && findBootstrapServerCert()) + deleteBootstrapServerCert(); + if (findCertificate(tokenname, nickname)) + deleteCert(tokenname, nickname); + if (certTag.equals("signing") && subsystem.equals("ca")) + CryptoUtil.importUserCertificate(impl, nickname); + else + CryptoUtil.importUserCertificate(impl, nickname, false); + CMS.debug( + "CertRequestPanel configCert: cert imported for certTag " + + certTag); + } catch (Exception ee) { + CMS.debug( + "CertRequestPanel configCert: import certificate for certTag=" + + certTag + " Exception: " + + ee.toString()); + CMS.debug("ok"); + // hasErr = true; + } + } + } else if (cert.getType().equals("remote")) { + if (b64 != null && b64.length() > 0 + && !b64.startsWith("...")) { + String b64chain = HttpInput.getCertChain(request, certTag + "_cc"); + CMS.debug( + "CertRequestPanel: in update() process remote...import cert"); + + String input = HttpInput.getCert(request, cert.getCertTag()); + + if (input != null) { + try { + if (certTag.equals("sslserver") && findBootstrapServerCert()) + deleteBootstrapServerCert(); + if (findCertificate(tokenname, nickname)) { + deleteCert(tokenname, nickname); + } + } catch (Exception e) { + CMS.debug("CertRequestPanel update (remote): deleteCert Exception=" + e.toString()); + } + input = CryptoUtil.stripCertBrackets(input.trim()); + String certs = CryptoUtil.normalizeCertStr(input); + byte[] certb = CryptoUtil.base64Decode(certs); + + config.putString(subsystem + "." + certTag + ".cert", + certs); + try { + CryptoManager cm = CryptoManager.getInstance(); + X509Certificate x509cert = cm.importCertPackage( + certb, nickname); + + CryptoUtil.trustCertByNickname(nickname); + X509Certificate[] certchains = cm.buildCertificateChain( + x509cert); + X509Certificate leaf = null; + + if (certchains != null) { + CMS.debug( + "CertRequestPanel certchains length=" + + certchains.length); + leaf = certchains[certchains.length - 1]; + } + + if (leaf == null) { + CMS.debug("CertRequestPanel::update() - " + + "leaf is null!"); + throw new IOException("leaf is null"); + } + + if (/*(certchains.length <= 1) &&*/ + (b64chain != null && b64chain.length() != 0)) { + CMS.debug("CertRequestPanel: cert might not have contained chain...calling importCertificateChain: " + + b64chain); + try { + CryptoUtil.importCertificateChain( + CryptoUtil.normalizeCertAndReq(b64chain)); + } catch (Exception e) { + CMS.debug("CertRequestPanel: importCertChain: Exception: " + e.toString()); + } + } + + InternalCertificate icert = (InternalCertificate) leaf; + + icert.setSSLTrust( + InternalCertificate.TRUSTED_CA + | InternalCertificate.TRUSTED_CLIENT_CA + | InternalCertificate.VALID_CA); + CMS.debug( + "CertRequestPanel configCert: import certificate successfully, certTag=" + + certTag); + } catch (Exception ee) { + CMS.debug( + "CertRequestPanel configCert: import certificate for certTag=" + + certTag + " Exception: " + + ee.toString()); + CMS.debug("ok"); + // hasErr=true; + } + } else { + CMS.debug("CertRequestPanel: in update() input null"); + hasErr = true; + } + } else { + CMS.debug("CertRequestPanel: in update() b64 not set"); + hasErr = true; + } + + } else { + b64 = CryptoUtil.stripCertBrackets(b64.trim()); + String certs = CryptoUtil.normalizeCertStr(b64); + byte[] certb = CryptoUtil.base64Decode(certs); + X509CertImpl impl = new X509CertImpl(certb); + try { + if (certTag.equals("sslserver") && findBootstrapServerCert()) + deleteBootstrapServerCert(); + if (findCertificate(tokenname, nickname)) { + deleteCert(tokenname, nickname); + } + } catch (Exception ee) { + CMS.debug("CertRequestPanel update: deleteCert Exception=" + ee.toString()); + } + + try { + if (certTag.equals("signing") && subsystem.equals("ca")) + CryptoUtil.importUserCertificate(impl, nickname); + else + CryptoUtil.importUserCertificate(impl, nickname, false); + } catch (Exception ee) { + CMS.debug("CertRequestPanel: Failed to import user certificate." + ee.toString()); + hasErr = true; + } + } + + //update requests in request queue for local certs to allow renewal + if ((cert.getType().equals("local")) || (cert.getType().equals("selfsign"))) { + CertUtil.updateLocalRequest(config, certTag, cert.getRequest(), "pkcs10", null); + } + + if (certTag.equals("signing") && subsystem.equals("ca")) { + String NickName = nickname; + if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) + NickName = tokenname + ":" + nickname; + + CMS.debug("CertRequestPanel update: set trust on CA signing cert " + NickName); + CryptoUtil.trustCertByNickname(NickName); + CMS.reinit(ICertificateAuthority.ID); + } + } //while loop + + if (hasErr == false) { + config.putBoolean("preop.CertRequestPanel.done", true); + } + config.commit(false); + } catch (Exception e) { + CMS.debug("CertRequestPanel: Exception caught: " + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + + //reset the attribute of the user certificate to u,u,u + String certlist = ""; + try { + certlist = config.getString("preop.cert.list", ""); + StringTokenizer tokenizer = new StringTokenizer(certlist, ","); + CryptoManager cm = CryptoManager.getInstance(); + while (tokenizer.hasMoreTokens()) { + String tag = tokenizer.nextToken(); + if (tag.equals("signing")) + continue; + String nickname = config.getString("preop.cert." + tag + ".nickname", ""); + String tokenname = config.getString("preop.module.token", ""); + if (!tokenname.equals("Internal Key Storage Token")) + nickname = tokenname + ":" + nickname; + X509Certificate c = cm.findCertByNickname(nickname); + if (c instanceof InternalCertificate) { + InternalCertificate ic = (InternalCertificate) c; + ic.setSSLTrust(InternalCertificate.USER); + ic.setEmailTrust(InternalCertificate.USER); + if (tag.equals("audit_signing")) { + ic.setObjectSigningTrust(InternalCertificate.USER + | InternalCertificate.VALID_PEER | InternalCertificate.TRUSTED_PEER); + } else { + ic.setObjectSigningTrust(InternalCertificate.USER); + } + } + } + } catch (Exception e) { + } + if (!hasErr) { + context.put("updateStatus", "success"); + } else { + context.put("updateStatus", "failure"); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Certificate Request"); + context.put("panel", "admin/console/config/certrequestpanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java b/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java new file mode 100644 index 000000000..e956edebe --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java @@ -0,0 +1,667 @@ +// --- 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.csadmin; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.math.BigInteger; +import java.util.Date; + +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPException; +import netscape.security.pkcs.PKCS10; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.crypto.X509Certificate; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.profile.CertInfoProfile; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.http.HttpClient; +import com.netscape.cmsutil.http.HttpRequest; +import com.netscape.cmsutil.http.HttpResponse; +import com.netscape.cmsutil.http.JssSSLSocketFactory; +import com.netscape.cmsutil.xml.XMLObject; + +public class CertUtil { + static final int LINE_COUNT = 76; + + public static X509CertImpl createRemoteCert(String hostname, + int port, String content, HttpServletResponse response, WizardPanelBase panel) + throws IOException { + HttpClient httpclient = new HttpClient(); + String c = null; + CMS.debug("CertUtil createRemoteCert: content " + content); + try { + JssSSLSocketFactory factory = new JssSSLSocketFactory(); + + httpclient = new HttpClient(factory); + httpclient.connect(hostname, port); + HttpRequest httprequest = new HttpRequest(); + + httprequest.setMethod(HttpRequest.POST); + httprequest.setURI("/ca/ee/ca/profileSubmit"); + httprequest.setHeader("user-agent", "HTTPTool/1.0"); + httprequest.setHeader("content-length", "" + content.length()); + httprequest.setHeader("content-type", + "application/x-www-form-urlencoded"); + httprequest.setContent(content); + HttpResponse httpresponse = httpclient.send(httprequest); + + c = httpresponse.getContent(); + } catch (Exception e) { + CMS.debug("CertUtil createRemoteCert: " + e.toString()); + throw new IOException(e.toString()); + } + + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("CertUtil::createRemoteCert() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + String status = parser.getValue("Status"); + + CMS.debug("CertUtil createRemoteCert: status=" + status); + if (status.equals("2")) { + //relogin to the security domain + panel.reloginSecurityDomain(response); + return null; + } else if (!status.equals("0")) { + String error = parser.getValue("Error"); + throw new IOException(error); + } + + String b64 = parser.getValue("b64"); + + CMS.debug("CertUtil createRemoteCert: " + b64); + b64 = CryptoUtil.normalizeCertAndReq(b64); + byte[] b = CryptoUtil.base64Decode(b64); + + return new X509CertImpl(b); + } catch (Exception e) { + CMS.debug("CertUtil createRemoteCert: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return null; + } + + public static String getPKCS10(IConfigStore config, String prefix, + Cert certObj, Context context) throws IOException { + String certTag = certObj.getCertTag(); + + X509Key pubk = null; + try { + String pubKeyType = config.getString( + prefix + certTag + ".keytype"); + String algorithm = config.getString( + prefix + certTag + ".keyalgorithm"); + if (pubKeyType.equals("rsa")) { + String pubKeyModulus = config.getString( + prefix + certTag + ".pubkey.modulus"); + String pubKeyPublicExponent = config.getString( + prefix + certTag + ".pubkey.exponent"); + pubk = CryptoUtil.getPublicX509Key( + CryptoUtil.string2byte(pubKeyModulus), + CryptoUtil.string2byte(pubKeyPublicExponent)); + } else if (pubKeyType.equals("ecc")) { + String pubKeyEncoded = config.getString( + prefix + certTag + ".pubkey.encoded"); + pubk = CryptoUtil.getPublicX509ECCKey( + CryptoUtil.string2byte(pubKeyEncoded)); + } else { + CMS.debug("CertRequestPanel::getPKCS10() - " + + "public key type is unsupported!"); + throw new IOException("public key type is unsupported"); + } + + if (pubk != null) { + CMS.debug("CertRequestPanel: got public key"); + } else { + CMS.debug("CertRequestPanel: error getting public key null"); + throw new IOException("public key is null"); + } + // get private key + String privKeyID = config.getString(prefix + certTag + ".privkey.id"); + byte[] keyIDb = CryptoUtil.string2byte(privKeyID); + + PrivateKey privk = CryptoUtil.findPrivateKeyFromID(keyIDb); + + if (privk != null) { + CMS.debug("CertRequestPanel: got private key"); + } else { + CMS.debug("CertRequestPanel: error getting private key null"); + } + + // construct cert request + String dn = config.getString(prefix + certTag + ".dn"); + + PKCS10 certReq = null; + certReq = CryptoUtil.createCertificationRequest(dn, pubk, + privk, algorithm); + byte[] certReqb = certReq.toByteArray(); + String certReqs = CryptoUtil.base64Encode(certReqb); + + return certReqs; + } catch (Throwable e) { + CMS.debug(e); + context.put("errorString", e.toString()); + CMS.debug("CertUtil getPKCS10: " + e.toString()); + throw new IOException(e.toString()); + } + } + + /* + * create requests so renewal can work on these initial certs + */ + public static IRequest createLocalRequest(IRequestQueue queue, String serialNum, X509CertInfo info) + throws EBaseException { + // RequestId rid = new RequestId(serialNum); + // just need a request, no need to get into a queue + // IRequest r = new EnrollmentRequest(rid); + CMS.debug("CertUtil: createLocalRequest for serial: " + serialNum); + IRequest req = queue.newRequest("enrollment"); + CMS.debug("certUtil: newRequest called"); + req.setExtData("profile", "true"); + req.setExtData("requestversion", "1.0.0"); + req.setExtData("req_seq_num", "0"); + req.setExtData(IEnrollProfile.REQUEST_CERTINFO, info); + req.setExtData(IEnrollProfile.REQUEST_EXTENSIONS, + new CertificateExtensions()); + req.setExtData("requesttype", "enrollment"); + req.setExtData("requestor_name", ""); + req.setExtData("requestor_email", ""); + req.setExtData("requestor_phone", ""); + req.setExtData("profileRemoteHost", ""); + req.setExtData("profileRemoteAddr", ""); + req.setExtData("requestnotes", ""); + req.setExtData("isencryptioncert", "false"); + req.setExtData("profileapprovedby", "system"); + + // mark request as complete + CMS.debug("certUtil: calling setRequestStatus"); + req.setRequestStatus(RequestStatus.COMPLETE); + + return req; + } + + /** + * update local cert request with the actual request + * called from CertRequestPanel.java + */ + public static void updateLocalRequest(IConfigStore config, String certTag, String certReq, String reqType, + String subjectName) { + try { + CMS.debug("Updating local request... certTag=" + certTag); + RequestId rid = new RequestId(config.getString("preop.cert." + certTag + ".reqId")); + + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem( + ICertificateAuthority.ID); + + IRequestQueue queue = ca.getRequestQueue(); + if (queue != null) { + IRequest req = queue.findRequest(rid); + if (req != null) { + if (!certReq.equals("")) + req.setExtData("cert_request", certReq); + req.setExtData("cert_request_type", reqType); + if (subjectName != null) { + req.setExtData("subject", subjectName); + new X500Name(subjectName); // check for errors + } + } + queue.updateRequest(req); + } else { + CMS.debug("CertUtil:updateLocalRequest - request queue = null"); + } + } catch (Exception e) { + CMS.debug("CertUtil:updateLocalRequest - Exception:" + e.toString()); + } + } + + /** + * reads from the admin cert profile caAdminCert.profile and takes the first + * entry in the list of allowed algorithms. Users that wish a different algorithm + * can specify it in the profile using default.params.signingAlg + */ + + public static String getAdminProfileAlgorithm(IConfigStore config) { + String algorithm = "SHA256withRSA"; + try { + String caSigningKeyType = config.getString("preop.cert.signing.keytype", "rsa"); + String pfile = config.getString("profile.caAdminCert.config"); + FileInputStream fis = new FileInputStream(pfile); + DataInputStream in = new DataInputStream(fis); + BufferedReader br = new BufferedReader(new InputStreamReader(in)); + + String strLine; + while ((strLine = br.readLine()) != null) { + String marker2 = "default.params.signingAlg="; + int indx = strLine.indexOf(marker2); + if (indx != -1) { + String alg = strLine.substring(indx + marker2.length()); + if ((alg.length() > 0) && (!alg.equals("-"))) { + algorithm = alg; + break; + } + ; + } + ; + + String marker = "signingAlgsAllowed="; + indx = strLine.indexOf(marker); + if (indx != -1) { + String[] algs = strLine.substring(indx + marker.length()).split(","); + for (int i = 0; i < algs.length; i++) { + if ((caSigningKeyType.equals("rsa") && (algs[i].indexOf("RSA") != -1)) || + (caSigningKeyType.equals("ecc") && (algs[i].indexOf("EC") != -1))) { + algorithm = algs[i]; + break; + } + } + } + } + in.close(); + } catch (Exception e) { + CMS.debug("getAdminProfleAlgorithm: exception: " + e); + } + return algorithm; + } + + public static X509CertImpl createLocalCert(IConfigStore config, X509Key x509key, + String prefix, String certTag, String type, Context context) throws IOException { + + CMS.debug("Creating local certificate... certTag=" + certTag); + String profile = null; + + try { + profile = config.getString(prefix + certTag + ".profile"); + } catch (Exception e) { + } + + X509CertImpl cert = null; + ICertificateAuthority ca = null; + ICertificateRepository cr = null; + RequestId reqId = null; + String profileId = null; + IRequestQueue queue = null; + IRequest req = null; + + try { + String dn = config.getString(prefix + certTag + ".dn"); + String keyAlgorithm = null; + Date date = new Date(); + + X509CertInfo info = null; + + if (certTag.equals("admin")) { + keyAlgorithm = getAdminProfileAlgorithm(config); + } else { + keyAlgorithm = config.getString(prefix + certTag + ".keyalgorithm"); + } + ca = (ICertificateAuthority) CMS.getSubsystem( + ICertificateAuthority.ID); + cr = (ICertificateRepository) ca.getCertificateRepository(); + BigInteger serialNo = cr.getNextSerialNumber(); + if (type.equals("selfsign")) { + CMS.debug("Creating local certificate... issuerdn=" + dn); + CMS.debug("Creating local certificate... dn=" + dn); + info = CryptoUtil.createX509CertInfo(x509key, serialNo.intValue(), dn, dn, date, + date, keyAlgorithm); + } else { + String issuerdn = config.getString("preop.cert.signing.dn", ""); + CMS.debug("Creating local certificate... issuerdn=" + issuerdn); + CMS.debug("Creating local certificate... dn=" + dn); + + info = CryptoUtil.createX509CertInfo(x509key, + serialNo.intValue(), issuerdn, dn, date, date, keyAlgorithm); + } + CMS.debug("Cert Template: " + info.toString()); + + String instanceRoot = config.getString("instanceRoot"); + + CertInfoProfile processor = new CertInfoProfile( + instanceRoot + "/conf/" + profile); + + // cfu - create request to enable renewal + try { + queue = ca.getRequestQueue(); + if (queue != null) { + req = createLocalRequest(queue, serialNo.toString(), info); + CMS.debug("CertUtil profile name= " + profile); + req.setExtData("req_key", x509key.toString()); + + // store original profile id in cert request + int idx = profile.lastIndexOf('.'); + if (idx == -1) { + CMS.debug("CertUtil profileName contains no ."); + req.setExtData("origprofileid", profile); + } else { + String name = profile.substring(0, idx); + req.setExtData("origprofileid", name); + } + + // store mapped profile ID for use in renewal + profileId = processor.getProfileIDMapping(); + req.setExtData("profileid", profileId); + req.setExtData("profilesetid", processor.getProfileSetIDMapping()); + + reqId = req.getRequestId(); + config.putString("preop.cert." + certTag + ".reqId", reqId.toString()); + } else { + CMS.debug("certUtil: requestQueue null"); + } + } catch (Exception e) { + CMS.debug("Creating local request exception:" + e.toString()); + } + + processor.populate(info); + + String caPriKeyID = config.getString( + prefix + "signing" + ".privkey.id"); + byte[] keyIDb = CryptoUtil.string2byte(caPriKeyID); + PrivateKey caPrik = CryptoUtil.findPrivateKeyFromID( + keyIDb); + + if (caPrik == null) { + CMS.debug("CertUtil::createSelfSignedCert() - " + + "CA private key is null!"); + throw new IOException("CA private key is null"); + } else { + CMS.debug("CertUtil createSelfSignedCert: got CA private key"); + } + + String keyAlgo = x509key.getAlgorithm(); + CMS.debug("key algorithm is " + keyAlgo); + String caSigningKeyType = + config.getString("preop.cert.signing.keytype", "rsa"); + String caSigningKeyAlgo = ""; + if (type.equals("selfsign")) { + caSigningKeyAlgo = config.getString("preop.cert.signing.keyalgorithm", "SHA256withRSA"); + } else { + caSigningKeyAlgo = config.getString("preop.cert.signing.signingalgorithm", "SHA256withRSA"); + } + + CMS.debug("CA Signing Key type " + caSigningKeyType); + CMS.debug("CA Signing Key algorithm " + caSigningKeyAlgo); + + if (caSigningKeyType.equals("ecc")) { + CMS.debug("CA signing cert is ECC"); + cert = CryptoUtil.signECCCert(caPrik, info, + caSigningKeyAlgo); + } else { + CMS.debug("CA signing cert is not ecc"); + cert = CryptoUtil.signCert(caPrik, info, + caSigningKeyAlgo); + } + + if (cert != null) { + CMS.debug("CertUtil createSelfSignedCert: got cert signed"); + } + } catch (Exception e) { + CMS.debug(e); + CMS.debug("NamePanel configCert() exception caught:" + e.toString()); + } + + if (cr == null) { + context.put("errorString", + "Ceritifcate Authority is not ready to serve."); + throw new IOException("Ceritifcate Authority is not ready to serve."); + } + + ICertRecord record = null; + try { + MetaInfo meta = new MetaInfo(); + if (reqId != null) { + meta.set(ICertRecord.META_REQUEST_ID, reqId.toString()); + } + + meta.set(ICertRecord.META_PROFILE_ID, profileId); + record = (ICertRecord) cr.createCertRecord( + cert.getSerialNumber(), cert, meta); + } catch (Exception e) { + CMS.debug( + "NamePanel configCert: failed to add metainfo. Exception: " + e.toString()); + } + + try { + cr.addCertificateRecord(record); + CMS.debug( + "NamePanel configCert: finished adding certificate record."); + } catch (Exception e) { + CMS.debug( + "NamePanel configCert: failed to add certificate record. Exception: " + + e.toString()); + try { + cr.deleteCertificateRecord(record.getSerialNumber()); + cr.addCertificateRecord(record); + } catch (Exception ee) { + CMS.debug("NamePanel update: Exception: " + ee.toString()); + } + } + + if (req != null) { + // update request with cert + req.setExtData(IEnrollProfile.REQUEST_ISSUED_CERT, cert); + + // store request in db + try { + CMS.debug("certUtil: before updateRequest"); + if (queue != null) { + queue.updateRequest(req); + } + } catch (Exception e) { + CMS.debug("Exception in updateRequest" + e); + } + } + + return cert; + } + + public static void addUserCertificate(X509CertImpl cert) { + IConfigStore cs = CMS.getConfigStore(); + int num = 0; + try { + num = cs.getInteger("preop.subsystem.count", 0); + } catch (Exception e) { + } + IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID)); + String id = "user" + num; + + try { + String sysType = cs.getString("cs.type", ""); + String machineName = cs.getString("machineName", ""); + String securePort = cs.getString("service.securePort", ""); + id = sysType + "-" + machineName + "-" + securePort; + } catch (Exception e1) { + // ignore + } + + num++; + cs.putInteger("preop.subsystem.count", num); + cs.putInteger("subsystem.count", num); + + try { + cs.commit(false); + } catch (Exception e) { + } + + IUser user = null; + X509CertImpl[] certs = new X509CertImpl[1]; + CMS.debug("CertUtil addUserCertificate starts"); + try { + user = system.createUser(id); + user.setFullName(id); + user.setEmail(""); + user.setPassword(""); + user.setUserType("agentType"); + user.setState("1"); + user.setPhone(""); + certs[0] = cert; + user.setX509Certificates(certs); + system.addUser(user); + CMS.debug("CertUtil addUserCertificate: successfully add the user"); + } catch (LDAPException e) { + CMS.debug("CertUtil addUserCertificate" + e.toString()); + if (e.getLDAPResultCode() != LDAPException.ENTRY_ALREADY_EXISTS) { + try { + user = system.getUser(id); + user.setX509Certificates(certs); + } catch (Exception ee) { + CMS.debug("CertUtil addUserCertificate: successfully find the user"); + } + } + } catch (Exception e) { + CMS.debug("CertUtil addUserCertificate addUser " + e.toString()); + } + + try { + system.addUserCert(user); + CMS.debug("CertUtil addUserCertificate: successfully add the user certificate"); + } catch (Exception e) { + CMS.debug("CertUtil addUserCertificate exception=" + e.toString()); + } + + IGroup group = null; + String groupName = "Subsystem Group"; + + try { + group = system.getGroupFromName(groupName); + if (!group.isMember(id)) { + group.addMemberName(id); + system.modifyGroup(group); + CMS.debug("CertUtil addUserCertificate: update: successfully added the user to the group."); + } + } catch (Exception e) { + CMS.debug("CertUtil addUserCertificate update: modifyGroup " + e.toString()); + } + } + + /* + * formats a cert fingerprints + */ + public static String fingerPrintFormat(String content) { + if (content == null || content.length() == 0) { + return ""; + } + + StringBuffer result = new StringBuffer(); + result.append("Fingerprints:\n"); + + while (content.length() >= LINE_COUNT) { + result.append(content.substring(0, LINE_COUNT)); + result.append("\n"); + content = content.substring(LINE_COUNT); + } + if (content.length() > 0) + result.append(content); + result.append("\n"); + + return result.toString(); + } + + public static boolean privateKeyExistsOnToken(String certTag, + String tokenname, String nickname) { + IConfigStore cs = CMS.getConfigStore(); + String givenid = ""; + try { + givenid = cs.getString("preop.cert." + certTag + ".privkey.id"); + } catch (Exception e) { + CMS.debug("CertUtil privateKeyExistsOnToken: we did not generate private key yet."); + return false; + } + + String fullnickname = nickname; + + if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) { + fullnickname = tokenname + ":" + nickname; + } + + X509Certificate cert = null; + CryptoManager cm = null; + try { + cm = CryptoManager.getInstance(); + cert = cm.findCertByNickname(fullnickname); + } catch (Exception e) { + CMS.debug("CertUtil privateKeyExistsOnToken: nickname=" + fullnickname + " Exception:" + e.toString()); + return false; + } + + PrivateKey privKey = null; + try { + privKey = cm.findPrivKeyByCert(cert); + } catch (Exception e) { + CMS.debug("CertUtil privateKeyExistsOnToken: cant find private key (" + + fullnickname + ") exception: " + e.toString()); + return false; + } + + if (privKey == null) { + CMS.debug("CertUtil privateKeyExistsOnToken: cant find private key (" + fullnickname + ")"); + return false; + } else { + String str = ""; + try { + str = CryptoUtil.byte2string(privKey.getUniqueID()); + } catch (Exception e) { + CMS.debug("CertUtil privateKeyExistsOnToken: encode string Exception: " + e.toString()); + } + + if (str.equals(givenid)) { + CMS.debug("CertUtil privateKeyExistsOnToken: find the private key on the token."); + return true; + } + } + + return false; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java b/base/common/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java new file mode 100644 index 000000000..52a98d540 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java @@ -0,0 +1,117 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.xml.XMLObject; + +public class CheckIdentity extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1647682040815275807L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + public CheckIdentity() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + CMS.debug("CheckIdentity init"); + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + try { + authenticate(cmsReq); + } catch (Exception e) { + CMS.debug("CheckIdentity authentication failed"); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + outputError(httpResp, "Error: Not authenticated"); + return; + } + + try { + XMLObject xmlObj = null; + + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + 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, ie, it will not return the default javascript. + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigBaseServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigBaseServlet.java new file mode 100644 index 000000000..dbda788f6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigBaseServlet.java @@ -0,0 +1,121 @@ +// --- 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.csadmin; + +import java.util.Enumeration; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; + +public abstract class ConfigBaseServlet extends BaseServlet { + /** + * + */ + private static final long serialVersionUID = 7692352201878710530L; + + public boolean isDisplayMode(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String display = request.getParameter("display"); + + if (display == null) { + return true; + } else { + return false; + } + } + + public abstract void display(HttpServletRequest request, + HttpServletResponse response, Context context); + + public abstract void update(HttpServletRequest request, + HttpServletResponse response, Context context); + + public abstract Template getTemplate(HttpServletRequest request, + HttpServletResponse response, + Context context); + + public void outputHttpParameters(HttpServletRequest httpReq) { + CMS.debug("ConfigBaseServlet:service() uri = " + httpReq.getRequestURI()); + @SuppressWarnings("unchecked") + Enumeration<String> paramNames = httpReq.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String pn = 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 (pn.startsWith("__") || + pn.endsWith("password") || + pn.endsWith("passwd") || + pn.endsWith("pwd") || + pn.equalsIgnoreCase("admin_password_again") || + pn.equalsIgnoreCase("directoryManagerPwd") || + pn.equalsIgnoreCase("bindpassword") || + pn.equalsIgnoreCase("bindpwd") || + pn.equalsIgnoreCase("passwd") || + pn.equalsIgnoreCase("password") || + pn.equalsIgnoreCase("pin") || + pn.equalsIgnoreCase("pwd") || + pn.equalsIgnoreCase("pwdagain") || + pn.equalsIgnoreCase("uPasswd")) { + CMS.debug("ConfigBaseServlet::service() param name='" + pn + + "' value='(sensitive)'"); + } else { + CMS.debug("ConfigBaseServlet::service() param name='" + pn + + "' value='" + httpReq.getParameter(pn) + "'"); + } + } + } + + /** + * Processes request. + */ + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + if (CMS.debugOn()) { + outputHttpParameters(request); + } + + if (isDisplayMode(request, response, context)) { + display(request, response, context); + } else { + update(request, response, context); + } + + Template template = null; + + try { + context.put("name", "Velocity Test"); + template = getTemplate(request, response, context); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java new file mode 100644 index 000000000..956c285b5 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java @@ -0,0 +1,33 @@ +// --- 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.csadmin; + +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; + +public class ConfigCertApprovalCallback + implements SSLCertificateApprovalCallback { + + public ConfigCertApprovalCallback() { + } + + public boolean approve(X509Certificate cert, + SSLCertificateApprovalCallback.ValidityStatus status) { + return true; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertReqServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertReqServlet.java new file mode 100644 index 000000000..b04de4144 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertReqServlet.java @@ -0,0 +1,50 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +public class ConfigCertReqServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = 4489288758636916446L; + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + Template template = null; + + try { + context.put("name", "Velocity Test"); + template = Velocity.getTemplate( + "admin/console/config/config_certreq.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCloneServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCloneServlet.java new file mode 100644 index 000000000..ed1d9cc07 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCloneServlet.java @@ -0,0 +1,50 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +public class ConfigCloneServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = -9065299591659111350L; + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + Template template = null; + + try { + context.put("name", "Velocity Test"); + template = Velocity.getTemplate( + "admin/console/config/config_clone.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigDatabaseServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigDatabaseServlet.java new file mode 100644 index 000000000..2b4a82a08 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigDatabaseServlet.java @@ -0,0 +1,196 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; + +public class ConfigDatabaseServlet extends ConfigBaseServlet { + + /** + * + */ + private static final long serialVersionUID = 2625626176089893989L; + private static final String HOST = "localhost"; + private static final String PORT = "389"; + private static final String BASEDN = "o=netscapeCertificateServer"; + private static final String BINDDN = "cn=Directory Manager"; + private static final String DATABASE = "userRoot"; + + public boolean isPanelModified() { + IConfigStore cs = CMS.getConfigStore(); + String modified = ""; + + try { + modified = cs.getString("preop.configDatabase.modified", ""); + } catch (Exception e) { + } + + if (modified.equals("true")) { + return true; + } else { + return false; + } + } + + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String hostname = null; + String portStr = null; + String basedn = null; + String binddn = null; + String bindpwd = ""; + String database = null; + + IConfigStore cs = CMS.getConfigStore(); + + if (isPanelModified()) { + try { + hostname = cs.getString("internaldb.ldapconn.host", ""); + portStr = cs.getString("internaldb.ldapconn.port", ""); + basedn = cs.getString("internaldb.basedn", ""); + binddn = cs.getString("internaldb.ldapauth.bindDN", ""); + database = cs.getString("internaldb.database", ""); + } catch (Exception e) { + } + } else { + hostname = HOST; + portStr = PORT; + basedn = BASEDN; + binddn = BINDDN; + database = DATABASE; + } + + context.put("hostname", hostname); + context.put("portStr", portStr); + context.put("basedn", basedn); + context.put("binddn", binddn); + context.put("bindpwd", bindpwd); + context.put("database", database); + context.put("displayStr", "initial"); + context.put("errorString", ""); + } + + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) { + IConfigStore cs = CMS.getConfigStore(); + String errorString = ""; + String hostname = request.getParameter("host"); + + if (hostname != null && hostname.length() > 0) { + cs.putString("internaldb.ldapconn.host", hostname); + } else { + errorString = "Host is empty string"; + } + + String portStr = request.getParameter("port"); + + if (portStr != null && portStr.length() > 0) { + int port = -1; + + try { + port = Integer.parseInt(portStr); + cs.putInteger("internaldb.ldapconn.port", port); + } catch (Exception e) { + errorString = "Port is invalid"; + } + } else { + errorString = "Port is empty string"; + } + + String basedn = request.getParameter("basedn"); + + if (basedn != null && basedn.length() > 0) { + cs.putString("internaldb.basedn", basedn); + } else { + errorString = "Base DN is empty string"; + } + + String binddn = request.getParameter("binddn"); + + if (binddn != null && binddn.length() > 0) { + cs.putString("internaldb.ldapauth.bindDN", binddn); + } else { + errorString = "Bind DN is empty string"; + } + + String database = request.getParameter("database"); + + if (database != null && database.length() > 0) { + cs.putString("internaldb.database", database); + } else { + errorString = "Database is empty string"; + } + + String bindpwd = request.getParameter("__bindpwd"); + IConfigStore psStore = null; + + if (bindpwd != null && bindpwd.length() > 0) { + String passwordFile = null; + + try { + passwordFile = cs.getString("passwordFile"); + psStore = CMS.createFileConfigStore(passwordFile); + } catch (Exception e) { + CMS.debug("ConfigDatabaseServlet update: " + e.toString()); + return; + } + psStore.putString("internaldb", bindpwd); + } else { + errorString = "Bind password is empty string"; + } + + cs.putString("preop.configDatabase.modified", "true"); + if (errorString.equals("")) { + try { + psStore.commit(false); + cs.commit(false); + } catch (Exception e) { + CMS.debug("ConfigDatabaseServlet update: " + e.toString()); + } + } + + context.put("hostname", hostname); + context.put("portStr", portStr); + context.put("basedn", basedn); + context.put("binddn", binddn); + context.put("bindpwd", bindpwd); + context.put("database", database); + context.put("displayStr", "loaded"); + context.put("errorString", errorString); + } + + public Template getTemplate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + try { + return Velocity.getTemplate("admin/console/config/config_db.vm"); + } catch (Exception e) { + } + return null; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java new file mode 100644 index 000000000..03233042c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java @@ -0,0 +1,296 @@ +// --- 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.csadmin; + +import java.io.FileNotFoundException; +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.util.IncorrectPasswordException; +import org.mozilla.jss.util.Password; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.password.PlainPasswordReader; +import com.netscape.cmsutil.password.PlainPasswordWriter; + +public class ConfigHSMLoginPanel extends WizardPanelBase { + private CryptoManager mCryptoManager = null; + private String mPwdFilePath = ""; + + public ConfigHSMLoginPanel() { + } + + public void init(ServletConfig config, int panelno) throws ServletException { + try { + mCryptoManager = CryptoManager.getInstance(); + mPwdFilePath = CMS.getConfigStore().getString( + "passwordFile"); + } catch (Exception e) { + CMS.debug("ConfigHSMLoginPanel: " + e.toString()); + } + setPanelNo(panelno); + setName("ConfigHSMLogin"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) throws ServletException { + try { + mCryptoManager = CryptoManager.getInstance(); + mPwdFilePath = CMS.getConfigStore().getString( + "passwordFile"); + } catch (Exception e) { + CMS.debug("ConfigHSMLoginPanel: " + e.toString()); + } + setPanelNo(panelno); + setName("ConfigHSMLogin"); + setId(id); + } + + public void cleanUp() throws IOException { + } + + public boolean isPanelDone() { + return true; + } + + public boolean isSubPanel() { + return true; + } + + public boolean isLoopbackPanel() { + return true; + } + + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + CMS.debug("ConfigHSMLoginPanel: in display()"); + context.put("title", "Security Module Login"); + + // get token selected to be logged in + String tokName = null; + tokName = HttpInput.getTokenName(request, "SecToken"); + + if (tokName != null) { + CMS.debug("ConfigHSMLoginPanel: selected token name= " + tokName); + } else { + CMS.debug("ConfigHSMLoginPanel: missing SecToken name"); + context.put("error", "noTokenName"); + context.put("panel", "admin/console/config/config_hsmloginpanel.vm"); + return; + } + CryptoToken token = null; + + try { + token = mCryptoManager.getTokenByName(tokName); + } catch (Exception e) { + CMS.debug( + "ConfigHSMLoginPanel: getTokenByName() failed: " + + e.toString()); + context.put("error", "tokenNotFound:" + tokName); + context.put("panel", "admin/console/config/config_hsmloginpanel.vm"); + return; + } + // first see if password in password file, try to login + PlainPasswordReader pr = new PlainPasswordReader(); + + try { + pr.init(mPwdFilePath); + } catch (Exception e) { + // is ok to not have it + CMS.debug("ConfigHSMLoginPanel: passwrd file path: " + e.toString()); + } + CMS.debug("ConfigHSMLoginPanel: checking if passwd in cache"); + String tokPwd = pr.getPassword("hardware-" + tokName); + + boolean loggedIn = false; + + if (tokPwd == null) { + CMS.debug("ConfigHSMLoginPanel: passwd not in cache"); + } else { + loggedIn = loginToken(token, tokPwd, context); + } + + if (!loggedIn) { + context.put("status", "display"); + } + context.put("panel", "admin/console/config/config_hsmloginpanel.vm"); + context.put("SecToken", tokName); + } + + // if logged in successfully, returns true + private boolean loginToken(CryptoToken token, String tokPwd, Context context) { + boolean rv = true; + Password password = null; + + password = new Password(tokPwd.toCharArray()); + + try { + if (token.passwordIsInitialized()) { + CMS.debug( + "ConfigHSMLoginPanel: loginToken():token password is initialized"); + if (!token.isLoggedIn()) { + CMS.debug( + "ConfigHSMLoginPanel: loginToken():Token is not logged in, try it"); + token.login(password); + context.put("status", "justLoggedIn"); + } else { + CMS.debug( + "ConfigHSMLoginPanel:Token has already logged on"); + context.put("status", "alreadyLoggedIn"); + } + } else { + CMS.debug( + "ConfigHSMLoginPanel: loginToken():Token password not initialized"); + context.put("status", "tokenPasswordNotInitialized"); + rv = false; + } + + } catch (IncorrectPasswordException e) { + context.put("status", "incorrectPassword"); + context.put("errorString", e.toString()); + CMS.debug("ConfigHSMLoginPanel: loginToken():" + e.toString()); + rv = false; + } catch (Exception e) { + CMS.debug("ConfigHSMLoginPanel: loginToken():" + e.toString()); + context.put("errorString", e.toString()); + rv = false; + } + return rv; + } + + // XXX how do you do this? + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + Descriptor choiceDesc = new Descriptor(IDescriptor.CHOICE, "", "", null); /* no default parameters */ + + set.add( + "choice", choiceDesc); + + return set; + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + CMS.debug("ConfigHSMLoginPanel: in update()"); + + String uTokName = null; + String uPasswd = null; + try { + uTokName = HttpInput.getTokenName(request, "uTokName"); + uPasswd = HttpInput.getPassword(request, "__uPasswd"); + } catch (Exception e) { + } + + if (uPasswd == null) { + CMS.debug("ConfigHSMLoginPanel: password not found"); + context.put("error", "no password"); + context.put("panel", "admin/console/config/config_hsmloginpanel.vm"); + context.put("updateStatus", "no password"); + return; + } else { + CMS.debug("ConfigHSMLoginPanel: got password"); + + CryptoToken token = null; + + try { + token = mCryptoManager.getTokenByName(uTokName); + } catch (Exception e) { + CMS.debug( + "ConfigHSMLoginPanel: getTokenByName() failed: " + + e.toString()); + context.put("error", "tokenNotFound:" + uTokName); + } + + try { + if (loginToken(token, uPasswd, context) == false) { + CMS.debug( + "ConfigHSMLoginPanel:loginToken failed for " + + uTokName); + context.put("error", "tokenLoginFailed"); + context.put("updateStatus", "login failed"); + context.put("panel", + "admin/console/config/config_hsmloginpanel.vm"); + return; + } + CMS.debug( + "ConfigHSMLoginPanel: update(): just logged in successfully"); + PlainPasswordWriter pw = new PlainPasswordWriter(); + + pw.init(mPwdFilePath); + pw.putPassword("hardware-" + uTokName, uPasswd); + pw.commit(); + + } catch (FileNotFoundException e) { + CMS.debug( + "ConfigHSMLoginPanel: update(): Exception caught: " + + e.toString() + " writing to " + mPwdFilePath); + CMS.debug( + "ConfigHSMLoginPanel: update(): password not written to cache"); + System.err.println("Exception caught: " + e.toString()); + context.put("error", "Exception:" + e.toString()); + } catch (Exception e) { + CMS.debug( + "ConfigHSMLoginPanel: update(): Exception caught: " + + e.toString()); + System.err.println("Exception caught: " + e.toString()); + context.put("error", "Exception:" + e.toString()); + } + + } // found password + + context.put("panel", "admin/console/config/config_hsmloginpanel.vm"); + context.put("status", "update"); + context.put("error", ""); + context.put("updateStatus", "success"); + + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Security Module Login"); + context.put("panel", "admin/console/config/config_hsmloginpanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMServlet.java new file mode 100644 index 000000000..9eb146294 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMServlet.java @@ -0,0 +1,297 @@ +// --- 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.csadmin; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.pkcs11.PK11Module; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.cmsutil.crypto.Module; + +public class ConfigHSMServlet extends ConfigBaseServlet { + /** + * + */ + private static final long serialVersionUID = -330521231753992202L; + private CryptoManager mCryptoManager = null; + private Vector<Module> mSupportedModules = null; + private Vector<Module> mOtherModules = null; + private String mDefaultTok = null; + private Hashtable<String, PK11Module> mCurrModTable = new Hashtable<String, PK11Module>(); + + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + public void loadCurrModTable() { + try { + // getting existing modules + mCryptoManager = CryptoManager.getInstance(); + @SuppressWarnings("unchecked") + Enumeration<PK11Module> modules = mCryptoManager.getModules(); + + while (modules.hasMoreElements()) { + PK11Module mod = modules.nextElement(); + + CMS.debug("ConfigHSMServlet: got module " + mod.getName()); + mCurrModTable.put(mod.getName(), mod); + } // while + } catch (Exception e) { + CMS.debug( + "ConfigHSMServlet: Exception caught in loadCurrModTable: " + + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + } + + /* + * Modules not listed as supported modules + */ + public void loadOtherModules() { + Enumeration<PK11Module> m = mCurrModTable.elements(); + + mOtherModules = new Vector<Module>(); + while (m.hasMoreElements()) { + PK11Module mod = m.nextElement(); + Enumeration<Module> s = mSupportedModules.elements(); + boolean found = false; + + while (s.hasMoreElements()) { + Module sm = s.nextElement(); + + if (mod.getName().equals(sm.getCommonName())) { + found = true; + break; + } else { + found = false; + } + }// while + if (!found) { + // unsupported, use common name as user friendly name + Module module = new Module(mod.getName(), mod.getName()); + + loadModTokens(module, mod); + module.setFound(true); + mOtherModules.addElement(module); + break; + } + }// while + } + + /* + * find all tokens belonging to a module and load the Module + */ + public void loadModTokens(Module module, PK11Module mod) { + @SuppressWarnings("unchecked") + Enumeration<CryptoToken> tokens = mod.getTokens(); + + while (tokens.hasMoreElements()) { + try { + CryptoToken token = tokens.nextElement(); + + CMS.debug("ConfigHSMServlet: token nick name=" + token.getName()); + CMS.debug( + "ConfigHSMServlet: token logged in?" + + token.isLoggedIn()); + CMS.debug( + "ConfigHSMServlet: token is present?" + + token.isPresent()); + if (!token.getName().equals("Internal Crypto Services Token")) { + module.addToken(token); + } else { + CMS.debug( + "ConfigHSMServlet: token " + token.getName() + + " not to be added"); + } + + } catch (TokenException ex) { + CMS.debug("ConfigHSMServlet:" + ex.toString()); + } + } + } + + /* + * Modules unsupported by the system will not be included + */ + public void loadSupportedModules() { + + // getting supported security modules + // a Vectgor of Modules + mSupportedModules = new Vector<Module>(); + // read from conf store all supported modules + try { + int count = CMS.getConfigStore().getInteger( + "preop.configModules.count"); + + CMS.debug("ConfigHSMServlet: supported modules count= " + count); + for (int i = 0; i < count; i++) { + String cn = CMS.getConfigStore().getString( + "preop.configModules.module" + i + ".commonName"); + String pn = CMS.getConfigStore().getString( + "preop.configModules.module" + i + ".userFriendlyName"); + String img = CMS.getConfigStore().getString( + "preop.configModules.module" + i + ".imagePath"); + + if ((cn == null) || (cn.equals(""))) { + break; + } + + CMS.debug("ConfigHSMServlet: got from config module: " + cn); + // create a Module object + Module module = new Module(cn, pn, img); + + if (mCurrModTable.containsKey(cn)) { + CMS.debug("ConfigHSMServlet: module found: " + cn); + module.setFound(true); + // add token info to module vector + PK11Module m = mCurrModTable.get(cn); + + loadModTokens(module, m); + } + + CMS.debug("ConfigHSMServlet: adding module " + cn); + // add module to set + if (!mSupportedModules.contains(module)) { + mSupportedModules.addElement(module); + } + }// for + + } catch (Exception e) { + CMS.debug( + "ConfigHSMServlet: Exception caught in loadSupportedModules(): " + + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + } + + public boolean isDisplayMode(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String choice = request.getParameter("choice"); + + if (choice == null) { + return true; + } else { + return false; + } + } + + public boolean isPanelModified(IConfigStore cs) { + String modified = ""; + + try { + modified = cs.getString("preop.configModules.modified", ""); + } catch (Exception e) { + return false; + } + + if (modified.equals("true")) { + return true; + } else { + return false; + } + } + + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("ConfigHSMServlet: in display()"); + + loadCurrModTable(); + loadSupportedModules(); + loadOtherModules(); + // getting default token selection + try { + mDefaultTok = CMS.getConfigStore().getString( + "preop.configModules.defaultTok", + "Internal Key Storage Token"); + } catch (Exception e) { + CMS.debug("ConfigHSMServlet: Exception caught: " + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + if (mSupportedModules == null) { + CMS.debug("ConfigHSMServlet: mSupportedModules not loaded"); + } else { + CMS.debug("ConfigHSMServlet: mSupportedModules loaded"); + } + + context.put("status", "display"); + context.put("oms", mOtherModules); + context.put("sms", mSupportedModules); + context.put("defTok", mDefaultTok); + } + + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + IConfigStore cs = CMS.getConfigStore(); + + CMS.debug("ConfigHSMServlet: in update()"); + + if (mSupportedModules == null) { + CMS.debug("ConfigHSMServlet: mSupportedModules not loaded"); + } else { + CMS.debug("ConfigHSMServlet: mSupportedModules loaded"); + } + + String select = request.getParameter("choice"); + + if (select == null) { + CMS.debug("ConfigHSMServlet: choice not found"); + // throw new IOException("choice not found"); + } + + try { + CMS.debug("ConfigHSMServlet: choice =" + select); + cs.putString("preop.configModules.defaultTok", select); + cs.commit(false); + } catch (Exception e) { + CMS.debug("ConfigHSMServlet: Exception caught: " + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + context.put("status", "update"); + context.put("error", ""); + + } + + public Template getTemplate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + try { + return Velocity.getTemplate("admin/console/config/config_hsm.vm"); + } catch (Exception e) { + } + return null; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigImportCertServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigImportCertServlet.java new file mode 100644 index 000000000..c65e559df --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigImportCertServlet.java @@ -0,0 +1,50 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +public class ConfigImportCertServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = 1907102921734394118L; + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + Template template = null; + + try { + context.put("name", "Velocity Test"); + template = Velocity.getTemplate( + "admin/console/config/config_importcert.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigJoinServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigJoinServlet.java new file mode 100644 index 000000000..5d50193cb --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigJoinServlet.java @@ -0,0 +1,182 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class ConfigJoinServlet extends ConfigBaseServlet { + + /** + * + */ + private static final long serialVersionUID = -5848083581083497909L; + + public boolean isDisplayMode(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String cert = request.getParameter("cert"); + + if (cert == null) { + return true; + } else { + return false; + } + } + + public boolean isPanelModified() { + IConfigStore config = CMS.getConfigStore(); + + String cert = null; + + try { + cert = config.getString("preop.join.cert", null); + } catch (EBaseException e) { + } + if (cert == null || cert.equals("")) { + return false; + } else { + return true; + } + } + + /** + * Displays panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + IConfigStore config = CMS.getConfigStore(); + + try { + String pubKeyModulus = config.getString( + "preop.keysize.pubKeyModulus"); + String pubKeyPublicExponent = config.getString( + "preop.keysize.pubKeyPublicExponent"); + String dn = config.getString("preop.name.dn"); + String priKeyID = config.getString("preop.keysize.priKeyID"); + String pkcs10 = CryptoUtil.getPKCS10FromKey(dn, + CryptoUtil.string2byte(pubKeyModulus), + CryptoUtil.string2byte(pubKeyPublicExponent), + CryptoUtil.string2byte(priKeyID)); + context.put("certreq", pkcs10); + } catch (Exception e) { + } + + String select = "auto"; + boolean select_manual = true; + + if (isPanelModified()) { + try { + select = config.getString("preop.join.select", null); + } catch (EBaseException e) { + CMS.debug("ConfigJoinServlet::display() - " + + "Exception=" + e.toString()); + return; + } + if (select.equals("auto")) { + + /* automated enrollment */ + select_manual = false; + } else { + try { + + /* manual enrollment */ + String cert = config.getString("preop.join.cert", ""); + + context.put("cert", cert); + } catch (EBaseException e) { + } + } + } else { + context.put("cert", ""); + } + if (select_manual) { + context.put("check_manual", "checked"); + context.put("check_auto", ""); + } else { + context.put("check_manual", ""); + context.put("check_auto", "checked"); + } + context.put("status", "display"); + } + + /** + * Updates panel. + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("JoinServlet: update"); + IConfigStore config = CMS.getConfigStore(); + String select = request.getParameter("choice"); + + try { + if (select.equals("manual")) { + + /* manual enrollment */ + CMS.debug("JoinServlet: manual"); + String certchain = request.getParameter("cert"); + + config.putString("preop.join.cert", certchain); + } else if (select.equals("auto")) { + CMS.debug("JoinServlet: auto"); + + /* automated enrollment */ + String url = request.getParameter("url"); + String uid = request.getParameter("uid"); + String pwd = request.getParameter("__pwd"); + + config.putString("preop.join.url", url); + config.putString("preop.join.uid", uid); + config.putString("preop.join.pwd", pwd); + + /* XXX - submit request to the CA, and import it automatically */ + config.putString( + "preop.join.cert", ""); /* store the chain */ + } + config.putString("preop.join.select", select); + config.commit(false); + } catch (Exception e) { + } + } + + public Template getTemplate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + Template template = null; + + try { + template = Velocity.getTemplate( + "admin/console/config/config_join.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigRootCAServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigRootCAServlet.java new file mode 100644 index 000000000..c9618db19 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigRootCAServlet.java @@ -0,0 +1,145 @@ +// --- 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.csadmin; + +import java.util.Vector; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.profile.CertInfoProfile; + +public class ConfigRootCAServlet extends ConfigBaseServlet { + + /** + * + */ + private static final long serialVersionUID = 1128630821163059659L; + + public boolean isDisplayMode(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String profile = request.getParameter("profile"); + + if (profile == null) { + return true; + } else { + return false; + } + } + + public boolean isPanelModified() { + IConfigStore config = CMS.getConfigStore(); + + String profile = null; + + try { + profile = config.getString("preop.hierarchy.profile", null); + } catch (EBaseException e) { + } + if (profile == null || profile.equals("")) { + return false; + } else { + return true; + } + } + + public Vector<CertInfoProfile> getProfiles() { + IConfigStore config = CMS.getConfigStore(); + String instancePath = ""; + + try { + instancePath = config.getString("instanceRoot"); + } catch (EBaseException e) { + } + String p[] = { "caCert.profile" }; + Vector<CertInfoProfile> profiles = new Vector<CertInfoProfile>(); + + for (int i = 0; i < p.length; i++) { + try { + profiles.addElement( + new CertInfoProfile(instancePath + "/conf/" + p[i])); + } catch (Exception e) { + } + } + return profiles; + } + + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + IConfigStore config = CMS.getConfigStore(); + String profile = null; + + if (isPanelModified()) { + try { + profile = config.getString("preop.hierarchy.profile", null); + } catch (EBaseException e) { + } + } + if (profile == null) { + profile = "caCert.profile"; + } + Vector<CertInfoProfile> profiles = getProfiles(); + + context.put("status", "display"); + context.put("profiles", profiles); + context.put("selected_profile_id", profile); + } + + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String profile = request.getParameter("profile"); + IConfigStore config = CMS.getConfigStore(); + + config.putString("preop.hierarchy.profile", profile); + try { + config.commit(false); + } catch (Exception e) { + } + context.put("status", "update"); + context.put("error", ""); + Vector<CertInfoProfile> profiles = getProfiles(); + + context.put("profiles", profiles); + context.put("selected_profile_id", profile); + } + + public Template getTemplate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + Template template = null; + + try { + template = Velocity.getTemplate( + "admin/console/config/config_rootca.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java new file mode 100644 index 000000000..9e430e2fd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java @@ -0,0 +1,299 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.net.URL; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class CreateSubsystemPanel extends WizardPanelBase { + + public CreateSubsystemPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Subsystem Selection"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Subsystem Type"); + setId(id); + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.subsystem.select", ""); + cs.putString("subsystem.select", ""); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.subsystem.select", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Subsystem Type"); + IConfigStore config = CMS.getConfigStore(); + String session_id = request.getParameter("session_id"); + if (session_id != null) { + CMS.debug("CreateSubsystemPanel setting session id."); + CMS.setConfigSDSessionId(session_id); + } + + String errorString = ""; + + if (isPanelDone()) { + try { + String s = config.getString("preop.subsystem.select"); + + if (s.equals("new")) { + context.put("check_newsubsystem", "checked"); + context.put("check_clonesubsystem", ""); + } else if (s.equals("clone")) { + context.put("check_newsubsystem", ""); + context.put("check_clonesubsystem", "checked"); + } + context.put("subsystemName", + config.getString("preop.subsystem.name")); + } catch (Exception e) { + CMS.debug(e.toString()); + } + } else { + context.put("check_newsubsystem", "checked"); + context.put("check_clonesubsystem", ""); + try { + context.put("subsystemName", + config.getString("preop.system.fullname")); + } catch (Exception e) { + CMS.debug(e.toString()); + } + } + + String cstype = ""; + + try { + cstype = config.getString("cs.type", ""); + context.put("cstype", cstype); + context.put("wizardname", config.getString("preop.wizard.name")); + context.put("systemname", config.getString("preop.system.name")); + context.put("fullsystemname", config.getString("preop.system.fullname")); + context.put("machineName", config.getString("machineName")); + context.put("http_port", CMS.getEENonSSLPort()); + context.put("https_agent_port", CMS.getAgentPort()); + context.put("https_ee_port", CMS.getEESSLPort()); + context.put("https_admin_port", CMS.getAdminPort()); + } catch (EBaseException e) { + } + + Vector<String> v = getUrlListFromSecurityDomain(config, cstype, "SecurePort"); + + StringBuffer list = new StringBuffer(); + int size = v.size(); + for (int i = 0; i < size; i++) { + if (i == size - 1) { + list.append(v.elementAt(i)); + } else { + list.append(v.elementAt(i)); + list.append(","); + } + } + + try { + config.putString("preop.master.list", list.toString()); + config.commit(false); + } catch (Exception e) { + errorString = "Internal error, cs.type is missing from CS.cfg"; + } + + if (list.length() == 0) + context.put("disableClone", "true"); + + context.put("panel", "admin/console/config/createsubsystempanel.vm"); + context.put("errorString", errorString); + context.put("urls", v); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + String errorString = ""; + IConfigStore config = CMS.getConfigStore(); + String select = HttpInput.getID(request, "choice"); + + if (select == null) { + CMS.debug("CreateSubsystemPanel: choice not found"); + context.put("updateStatus", "failure"); + throw new IOException("choice not found"); + } + + config.putString("preop.subsystem.name", + HttpInput.getName(request, "subsystemName")); + if (select.equals("newsubsystem")) { + config.putString("preop.subsystem.select", "new"); + config.putString("subsystem.select", "New"); + } else if (select.equals("clonesubsystem")) { + String cstype = ""; + try { + cstype = config.getString("cs.type", ""); + } catch (Exception e) { + } + + cstype = toLowerCaseSubsystemType(cstype); + + config.putString("preop.subsystem.select", "clone"); + config.putString("subsystem.select", "Clone"); + + String lists = ""; + try { + lists = config.getString("preop.cert.list", ""); + } catch (Exception ee) { + } + + StringTokenizer t = new StringTokenizer(lists, ","); + while (t.hasMoreTokens()) { + String tag = t.nextToken(); + if (tag.equals("sslserver")) + config.putBoolean(PCERT_PREFIX + tag + ".enable", true); + else + config.putBoolean(PCERT_PREFIX + tag + ".enable", false); + } + + // get the master CA + String index = request.getParameter("urls"); + String url = ""; + + try { + int x = Integer.parseInt(index); + String list = config.getString("preop.master.list", ""); + StringTokenizer tokenizer = new StringTokenizer(list, ","); + int counter = 0; + + while (tokenizer.hasMoreTokens()) { + url = tokenizer.nextToken(); + if (counter == x) { + break; + } + counter++; + } + } catch (Exception e) { + } + + url = url.substring(url.indexOf("http")); + + URL u = new URL(url); + String host = u.getHost(); + int https_ee_port = u.getPort(); + + String https_admin_port = getSecurityDomainAdminPort(config, + host, + String.valueOf(https_ee_port), + cstype); + + config.putString("preop.master.hostname", host); + config.putInteger("preop.master.httpsport", https_ee_port); + config.putString("preop.master.httpsadminport", https_admin_port); + + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + if (cstype.equals("ca")) { + updateCertChainUsingSecureEEPort(config, "clone", host, https_ee_port, + true, context, certApprovalCallback); + } + + getTokenInfo(config, cstype, host, https_ee_port, true, context, + certApprovalCallback); + } else { + CMS.debug("CreateSubsystemPanel: invalid choice " + select); + errorString = "Invalid choice"; + context.put("updateStatus", "failure"); + throw new IOException("invalid choice " + select); + } + + try { + config.commit(false); + } catch (EBaseException e) { + } + + context.put("errorString", errorString); + context.put("updateStatus", "success"); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Subsystem Type"); + context.put("panel", "admin/console/config/createsubsystempanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java new file mode 100644 index 000000000..82c45d1cd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java @@ -0,0 +1,1591 @@ +// --- 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.csadmin; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Random; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPDN; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPModification; +import netscape.ldap.LDAPSearchConstraints; +import netscape.ldap.LDAPSearchResults; +import netscape.ldap.LDAPv3; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.IDBSubsystem; +import com.netscape.certsrv.ldap.ILdapConnFactory; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.ldap.LDAPUtil; + +public class DatabasePanel extends WizardPanelBase { + + private static final String HOST = "localhost"; + private static final String CLONE_HOST = "Enter FQDN here"; + private static final String PORT = "389"; + private static final String BINDDN = "cn=Directory Manager"; + + private WizardServlet mServlet = null; + + public DatabasePanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Internal Database"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Internal Database"); + setId(id); + mServlet = servlet; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putBoolean("preop.Database.done", false); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + boolean s = cs.getBoolean("preop.Database.done", + false); + + if (s != true) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + Descriptor hostDesc = new Descriptor(IDescriptor.STRING, null, null, + "Host name"); + + set.add("hostname", hostDesc); + + Descriptor portDesc = new Descriptor(IDescriptor.INTEGER, null, null, + "Port"); + + set.add("portStr", portDesc); + + Descriptor basednDesc = new Descriptor(IDescriptor.STRING, null, null, + "Base DN"); + + set.add("basedn", basednDesc); + + Descriptor binddnDesc = new Descriptor(IDescriptor.STRING, null, null, + "Bind DN"); + + set.add("binddn", binddnDesc); + + Descriptor bindpwdDesc = new Descriptor(IDescriptor.PASSWORD, null, null, + "Bind Password"); + + set.add("bindpwd", bindpwdDesc); + + Descriptor databaseDesc = new Descriptor(IDescriptor.STRING, null, null, + "Database"); + + set.add("database", databaseDesc); + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("DatabasePanel: display()"); + context.put("title", "Internal Database"); + context.put("firsttime", "false"); + IConfigStore cs = CMS.getConfigStore(); + String hostname = null; + String portStr = null; + String basedn = null; + String binddn = null; + String bindpwd = ""; + String database = null; + String errorString = ""; + String secure = "false"; + String masterReplicationPort = ""; + String cloneReplicationPort = ""; + String replicationSecurity = ""; + + try { + @SuppressWarnings("unused") + String s = cs.getString("preop.database.removeData"); // check whether it's first time + } catch (Exception e) { + context.put("firsttime", "true"); + } + + String select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + if (isPanelDone()) { + try { + hostname = cs.getString("internaldb.ldapconn.host", ""); + portStr = cs.getString("internaldb.ldapconn.port", ""); + basedn = cs.getString("internaldb.basedn", ""); + binddn = cs.getString("internaldb.ldapauth.bindDN", ""); + database = cs.getString("internaldb.database", ""); + secure = cs.getString("internaldb.ldapconn.secureConn", ""); + replicationSecurity = cs.getString("internaldb.ldapconn.replicationSecurity", "None"); + masterReplicationPort = cs.getString("internaldb.ldapconn.masterReplicationPort", ""); + cloneReplicationPort = cs.getString("internaldb.ldapconn.cloneReplicationPort", ""); + errorString = cs.getString("preop.database.errorString", ""); + } catch (Exception e) { + CMS.debug("DatabasePanel display: " + e.toString()); + } + } else if (select.equals("clone")) { + hostname = CLONE_HOST; + portStr = PORT; + try { + basedn = cs.getString("internaldb.basedn", ""); + } catch (Exception e) { + CMS.debug("DatabasePanel::display() - " + + "Exception=" + e.toString()); + return; + } + binddn = BINDDN; + database = basedn.substring(basedn.lastIndexOf('=') + 1); + CMS.debug("Clone: database=" + database); + } else { + hostname = HOST; + portStr = PORT; + String instanceId = ""; + String machineName = ""; + + try { + instanceId = cs.getString("instanceId", ""); + machineName = cs.getString("machineName", ""); + } catch (Exception e) { + CMS.debug("DatabasePanel display: " + e.toString()); + } + String suffix = "dc=" + machineName + "-" + instanceId; + + boolean multipleEnable = false; + try { + multipleEnable = cs.getBoolean( + "internaldb.multipleSuffix.enable", false); + } catch (Exception e) { + } + + if (multipleEnable) + basedn = "ou=" + instanceId + "," + suffix; + else + basedn = suffix; + binddn = BINDDN; + database = machineName + "-" + instanceId; + } + + context.put("clone", select); + context.put("hostname", hostname); + context.put("portStr", portStr); + context.put("basedn", basedn); + context.put("binddn", binddn); + context.put("bindpwd", bindpwd); + context.put("database", database); + context.put("secureConn", (secure.equals("true") ? "on" : "off")); + context.put("masterReplicationPort", masterReplicationPort); + context.put("cloneReplicationPort", cloneReplicationPort); + context.put("replicationSecurity", replicationSecurity); + context.put("panel", "admin/console/config/databasepanel.vm"); + context.put("errorString", errorString); + } + + public void initParams(HttpServletRequest request, Context context) + throws IOException { + IConfigStore config = CMS.getConfigStore(); + String select = ""; + try { + select = config.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + context.put("clone", select); + context.put("hostname", (request.getParameter("host") != null) ? request.getParameter("host") : ""); + context.put("portStr", (request.getParameter("port") != null) ? request.getParameter("port") : ""); + context.put("basedn", (request.getParameter("basedn") != null) ? request.getParameter("basedn") : ""); + context.put("binddn", (request.getParameter("binddn") != null) ? request.getParameter("binddn") : ""); + context.put("bindpwd", (request.getParameter("__bindpwd") != null) ? + request.getParameter("__bindpwd"): ""); + context.put("database", (request.getParameter("database") != null) ? + request.getParameter("database") : ""); + context.put("masterReplicationPort", (request.getParameter("masterReplicationPort") != null) ? + request.getParameter("masterReplicationPort"): ""); + context.put("cloneReplicationPort", (request.getParameter("cloneReplicationPort") != null) ? + request.getParameter("cloneReplicationPort"): ""); + context.put("replicationSecurity", (request.getParameter("replicationSecurity") != null) ? + request.getParameter("replicationSecurity"): "None"); + } + + /** + * Parses and validates the parameters in the request. + */ + public void parseParameters(HttpServletRequest request, + HttpServletResponse response, Context context) throws IOException { + IConfigStore cs = CMS.getConfigStore(); + + String select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + String hostname = HttpInput.getHostname(request, "host"); + if (hostname == null || hostname.length() == 0) { + throw new IOException("hostname is empty string"); + } + context.put("hostname", hostname); + + // this validates that port is an integer + String portStr = HttpInput.getPortNumber(request, "port"); + context.put("portStr", portStr); + + String basedn = HttpInput.getDN(request, "basedn"); + if (basedn == null || basedn.length() == 0) { + throw new IOException("basedn is empty string"); + } + context.put("basedn", basedn); + + String binddn = HttpInput.getDN(request, "binddn"); + if (binddn == null || binddn.length() == 0) { + throw new IOException("binddn is empty string"); + } + context.put("binddn", binddn); + + String database = HttpInput.getLdapDatabase(request, "database"); + if (database == null || database.length() == 0) { + throw new IOException("Database is empty string"); + } + context.put("database", database); + + String bindpwd = HttpInput.getPassword(request, "__bindpwd"); + if (bindpwd == null || bindpwd.length() == 0) { + throw new IOException("Bind password is empty string"); + } + context.put("bindpwd", bindpwd); + + String secure = HttpInput.getCheckbox(request, "secureConn"); + context.put("secureConn", secure); + + String masterReplicationPort = HttpInput.getString(request, "masterReplicationPort"); + if (masterReplicationPort != null && masterReplicationPort.length() > 0) { + try { + Integer.parseInt(masterReplicationPort); // check for errors + } catch (NumberFormatException e) { + throw new IOException("Master replication port is invalid"); + } + } + context.put("masterReplicationPort", masterReplicationPort); + + String cloneReplicationPort = HttpInput.getString(request, "cloneReplicationPort"); + if (cloneReplicationPort != null && cloneReplicationPort.length() > 0) { + try { + Integer.parseInt(cloneReplicationPort); // check for errors + } catch (Exception e) { + throw new IOException("Clone replication port is invalid"); + } + } + context.put("cloneReplicationPort", cloneReplicationPort); + + String replicationSecurity = HttpInput.getString(request, "replicationSecurity"); + context.put("replicationSecurity", replicationSecurity); + + if (select.equals("clone")) { + String masterhost = ""; + String masterport = ""; + String masterbasedn = ""; + String realhostname = ""; + try { + masterhost = cs.getString("preop.internaldb.master.ldapconn.host", ""); + masterport = cs.getString("preop.internaldb.master.ldapconn.port", ""); + masterbasedn = cs.getString("preop.internaldb.master.basedn", ""); + realhostname = cs.getString("machineName", ""); + } catch (Exception e) { + } + + if (masterhost.equals(realhostname) && masterport.equals(portStr)) { + throw new IOException("Master and clone must not share the same internal database"); + } + + if (!masterbasedn.equals(basedn)) { + throw new IOException("Master and clone should have the same base DN"); + } + } + + context.put("errorString", ""); + cs.putString("preop.database.errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + + IConfigStore cs = CMS.getConfigStore(); + context.put("firsttime", "false"); + try { + @SuppressWarnings("unused") + String s = cs.getString("preop.database.removeData"); // check whether it's first time + } catch (Exception e) { + context.put("firsttime", "true"); + } + + try { + parseParameters(request, response, context); + } catch (IOException e) { + context.put("errorString", e.getMessage()); + cs.putString("preop.database.errorString", e.getMessage()); + context.put("updateStatus", "validate-failure"); + throw e; + } + + context.put("errorString", ""); + cs.putString("preop.database.errorString", ""); + } + + private LDAPConnection getLocalLDAPConn(Context context, String secure) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + + String host = ""; + String port = ""; + String pwd = ""; + String binddn = ""; + String security = ""; + + try { + host = cs.getString("internaldb.ldapconn.host"); + port = cs.getString("internaldb.ldapconn.port"); + binddn = cs.getString("internaldb.ldapauth.bindDN"); + pwd = (String) context.get("bindpwd"); + security = cs.getString("internaldb.ldapconn.secureConn"); + } catch (Exception e) { + CMS.debug("DatabasePanel populateDB: " + e.toString()); + throw new IOException( + "Failed to retrieve LDAP information from CS.cfg."); + } + + int p = -1; + + try { + p = Integer.parseInt(port); + } catch (Exception e) { + CMS.debug("DatabasePanel populateDB: " + e.toString()); + throw new IOException("Port is not valid"); + } + + LDAPConnection conn = null; + if (security.equals("true")) { + CMS.debug("DatabasePanel populateDB: creating secure (SSL) connection for internal ldap"); + conn = new LDAPConnection(CMS.getLdapJssSSLSocketFactory()); + } else { + CMS.debug("DatabasePanel populateDB: creating non-secure (non-SSL) connection for internal ldap"); + conn = new LDAPConnection(); + } + + CMS.debug("DatabasePanel connecting to " + host + ":" + p); + try { + conn.connect(host, p, binddn, pwd); + } catch (LDAPException e) { + CMS.debug("DatabasePanel populateDB: " + e.toString()); + throw new IOException("Failed to connect to the internal database."); + } + + return conn; + } + + private boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + for (int i = 0; i < children.length; i++) { + boolean success = deleteDir(new File(dir, children[i])); + if (!success) { + return false; + } + } + } + + // The directory is now empty so delete it + return dir.delete(); + } + + private void cleanupDB(LDAPConnection conn, String baseDN, String database) { + String[] entries = {}; + String filter = "objectclass=*"; + LDAPSearchConstraints cons = null; + String[] attrs = null; + String dn = ""; + try { + CMS.debug("Deleting baseDN: " + baseDN); + LDAPSearchResults res = conn.search(baseDN, LDAPConnection.SCOPE_BASE, filter, + attrs, true, cons); + if (res != null) + deleteEntries(res, conn, baseDN, entries); + } catch (LDAPException e) { + } + + try { + dn = "cn=mapping tree, cn=config"; + filter = "nsslapd-backend=" + database; + LDAPSearchResults res = conn.search(dn, LDAPConnection.SCOPE_ONE, filter, + attrs, true, cons); + if (res != null) { + while (res.hasMoreElements()) { + dn = res.next().getDN(); + filter = "objectclass=*"; + LDAPSearchResults res2 = conn.search(dn, LDAPConnection.SCOPE_BASE, filter, + attrs, true, cons); + if (res2 != null) + deleteEntries(res2, conn, dn, entries); + } + } + } catch (LDAPException e) { + } + + try { + dn = "cn=" + database + ",cn=ldbm database, cn=plugins, cn=config"; + LDAPSearchResults res = conn.search(dn, LDAPConnection.SCOPE_BASE, filter, + attrs, true, cons); + if (res != null) { + deleteEntries(res, conn, dn, entries); + String dbdir = getInstanceDir(conn) + "/db/" + database; + if (dbdir != null) { + CMS.debug(" Deleting dbdir " + dbdir); + boolean success = deleteDir(new File(dbdir)); + if (!success) { + CMS.debug("Unable to delete database directory " + dbdir); + } + } + } + } catch (LDAPException e) { + } + } + + private void populateDB(HttpServletRequest request, Context context, String secure) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + + String baseDN = ""; + String database = ""; + String dn = ""; + + try { + baseDN = cs.getString("internaldb.basedn"); + database = cs.getString("internaldb.database", ""); + } catch (Exception e) { + CMS.debug("DatabasePanel populateDB: " + e.toString()); + throw new IOException( + "Failed to retrieve LDAP information from CS.cfg."); + } + + String remove = HttpInput.getID(request, "removeData"); + LDAPConnection conn = getLocalLDAPConn(context, secure); + + // check that the database and baseDN do not exist + + boolean foundBaseDN = false; + boolean foundDatabase = false; + try { + LDAPEntry entry = conn.read(baseDN); + if (entry != null) + foundBaseDN = true; + } catch (LDAPException e) { + switch (e.getLDAPResultCode()) { + case LDAPException.NO_SUCH_OBJECT: + break; + default: + CMS.debug("DatabasePanel update: LDAPException " + e.toString()); + throw new IOException("Failed to create the database"); + } + } + + try { + dn = "cn=" + database + ",cn=ldbm database, cn=plugins, cn=config"; + LDAPEntry entry = conn.read(dn); + if (entry != null) + foundDatabase = true; + } catch (LDAPException e) { + switch (e.getLDAPResultCode()) { + case LDAPException.NO_SUCH_OBJECT: + break; + default: + CMS.debug("DatabasePanel update: LDAPException " + e.toString()); + throw new IOException("Failed to create the database"); + } + } + try { + dn = "cn=\"" + baseDN + "\",cn=mapping tree, cn=config"; + LDAPEntry entry = conn.read(dn); + if (entry != null) + foundDatabase = true; + } catch (LDAPException e) { + switch (e.getLDAPResultCode()) { + case LDAPException.NO_SUCH_OBJECT: + break; + default: + CMS.debug("DatabasePanel update: LDAPException " + e.toString()); + throw new IOException("Failed to create the database"); + } + } + + if (foundDatabase) { + CMS.debug("DatabasePanel update: This database has already been used."); + if (remove == null) { + throw new IOException( + "This database has already been used. Select the checkbox below to remove all data and reuse this database"); + } else { + CMS.debug("DatabasePanel update: Deleting existing DB and reusing base DN"); + cleanupDB(conn, baseDN, database); + foundBaseDN = false; + foundDatabase = false; + } + } + + if (foundBaseDN) { + CMS.debug("DatabasePanel update: This base DN has already been used."); + if (remove == null) { + throw new IOException( + "This base DN (" + + baseDN + + ") has already been used. Select the checkbox below to remove all data and reuse this base DN"); + } else { + CMS.debug("DatabasePanel update: Deleting existing DB and reusing base DN"); + cleanupDB(conn, baseDN, database); + foundBaseDN = false; + foundDatabase = false; + } + } + + // create database + try { + LDAPAttributeSet attrs = new LDAPAttributeSet(); + String oc[] = { "top", "extensibleObject", "nsBackendInstance" }; + attrs.add(new LDAPAttribute("objectClass", oc)); + attrs.add(new LDAPAttribute("cn", database)); + attrs.add(new LDAPAttribute("nsslapd-suffix", baseDN)); + dn = "cn=" + database + ",cn=ldbm database, cn=plugins, cn=config"; + LDAPEntry entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } catch (Exception e) { + CMS.debug("Warning: database creation error - " + e.toString()); + throw new IOException("Failed to create the database."); + } + + try { + LDAPAttributeSet attrs = new LDAPAttributeSet(); + String oc2[] = { "top", "extensibleObject", "nsMappingTree" }; + attrs.add(new LDAPAttribute("objectClass", oc2)); + attrs.add(new LDAPAttribute("cn", baseDN)); + attrs.add(new LDAPAttribute("nsslapd-backend", database)); + attrs.add(new LDAPAttribute("nsslapd-state", "Backend")); + dn = "cn=\"" + baseDN + "\",cn=mapping tree, cn=config"; + LDAPEntry entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } catch (Exception e) { + CMS.debug("Warning: database mapping tree creation error - " + e.toString()); + throw new IOException("Failed to create the database."); + } + + try { + // create base dn + CMS.debug("Creating base DN: " + baseDN); + String dns3[] = LDAPDN.explodeDN(baseDN, false); + StringTokenizer st = new StringTokenizer(dns3[0], "="); + String n = st.nextToken(); + String v = st.nextToken(); + LDAPAttributeSet attrs = new LDAPAttributeSet(); + String oc3[] = { "top", "domain" }; + if (n.equals("o")) { + oc3[1] = "organization"; + } else if (n.equals("ou")) { + oc3[1] = "organizationalUnit"; + } + attrs.add(new LDAPAttribute("objectClass", oc3)); + attrs.add(new LDAPAttribute(n, v)); + + LDAPEntry entry = new LDAPEntry(baseDN, attrs); + conn.add(entry); + } catch (Exception e) { + CMS.debug("Warning: suffix creation error - " + e.toString()); + throw new IOException("Failed to create the base DN: " + baseDN); + } + + // check to see if the base dn exists + CMS.debug("DatabasePanel checking existing " + baseDN); + + try { + LDAPEntry entry = conn.read(baseDN); + + if (entry != null) { + foundBaseDN = true; + } + } catch (LDAPException e) { + } + boolean createBaseDN = true; + + boolean testing = false; + try { + testing = cs.getBoolean("internaldb.multipleSuffix.enable", false); + } catch (Exception e) { + } + + if (!foundBaseDN) { + if (!testing) { + context.put("errorString", + "Base DN was not found. Please make sure to create the suffix in the internal database."); + throw new IOException("Base DN not found"); + } + + if (createBaseDN) { + // only auto create if it is an ou entry + String dns1[] = LDAPDN.explodeDN(baseDN, false); + + if (dns1 == null) { + throw new IOException("Invalid base DN"); + } + if (!dns1[0].startsWith("ou")) { + throw new IOException( + "Failed to find base DN, and failed to create non ou entry."); + } + String dns2[] = LDAPDN.explodeDN(baseDN, true); + // support only one level creation - create new entry + // right under the suffix + LDAPAttributeSet attrs = new LDAPAttributeSet(); + String oc[] = { "top", "organizationalUnit" }; + + attrs.add(new LDAPAttribute("objectClass", oc)); + attrs.add(new LDAPAttribute("ou", dns2[0])); + LDAPEntry entry = new LDAPEntry(baseDN, attrs); + + try { + conn.add(entry); + foundBaseDN = true; + CMS.debug("DatabasePanel added " + baseDN); + } catch (LDAPException e) { + throw new IOException("Failed to create " + baseDN); + } + } + } + if (!foundBaseDN) { + throw new IOException("Failed to find base DN"); + } + + String select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + if (select.equals("clone")) { + // if this is clone, add index before replication + // don't put in the schema or bad things will happen + importLDIFS("preop.internaldb.ldif", conn); + importLDIFS("preop.internaldb.index_ldif", conn); + importLDIFS("preop.internaldb.manager_ldif", conn); + } else { + // data will be replicated from the master to the clone + // so clone does not need the data + importLDIFS("preop.internaldb.schema.ldif", conn); + importLDIFS("preop.internaldb.ldif", conn); + importLDIFS("preop.internaldb.data_ldif", conn); + importLDIFS("preop.internaldb.index_ldif", conn); + importLDIFS("preop.internaldb.manager_ldif", conn); + } + + try { + conn.disconnect(); + } catch (LDAPException e) { + } + } + + private void importLDIFS(String param, LDAPConnection conn) throws IOException { + IConfigStore cs = CMS.getConfigStore(); + String v = null; + + CMS.debug("DatabasePanel populateDB param=" + param); + try { + v = cs.getString(param); + } catch (EBaseException e) { + CMS.debug("DatabasePanel populateDB: " + e.toString()); + throw new IOException("Cant find ldif files."); + } + + StringTokenizer tokenizer = new StringTokenizer(v, ","); + String baseDN = null; + String database = null; + + try { + baseDN = cs.getString("internaldb.basedn"); + } catch (EBaseException e) { + throw new IOException("internaldb.basedn is missing."); + } + + try { + database = cs.getString("internaldb.database"); + CMS.debug("DatabasePanel update: database=" + database); + } catch (EBaseException e) { + CMS.debug( + "DatabasePanel update: Failed to get database name. Exception: " + + e.toString()); + database = "userRoot"; + } + + String instancePath = null; + + try { + instancePath = cs.getString("instanceRoot"); + } catch (EBaseException e) { + throw new IOException("instanceRoot is missing"); + } + + String instanceId = null; + + try { + instanceId = cs.getString("instanceId"); + } catch (EBaseException e) { + throw new IOException("instanceId is missing"); + } + + String dbuser = null; + try { + dbuser = "uid=" + cs.getString("cs.type") + "-" + cs.getString("machineName") + "-" + + cs.getString("service.securePort") + ",ou=people," + baseDN; + } catch (EBaseException e) { + CMS.debug("Unable to construct dbuser" + e.toString()); + e.printStackTrace(); + throw new IOException("unable to construct dbuser"); + } + + String configDir = instancePath + File.separator + "conf"; + + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken().trim(); + int index = token.lastIndexOf("/"); + String name = token; + + if (index != -1) { + name = token.substring(index + 1); + } + + CMS.debug("DatabasePanel importLDIFS: ldif file = " + token); + String filename = configDir + File.separator + name; + + CMS.debug("DatabasePanel importLDIFS: ldif file copy to " + filename); + PrintStream ps = null; + BufferedReader in = null; + + try { + in = new BufferedReader(new FileReader(token)); + ps = new PrintStream(new FileOutputStream(filename, false)); + while (in.ready()) { + String s = in.readLine(); + int n = s.indexOf("{"); + + if (n == -1) { + ps.println(s); + } else { + boolean endOfline = false; + + while (n != -1) { + ps.print(s.substring(0, n)); + int n1 = s.indexOf("}"); + String tok = s.substring(n + 1, n1); + + if (tok.equals("instanceId")) { + ps.print(instanceId); + } else if (tok.equals("rootSuffix")) { + ps.print(baseDN); + } else if (tok.equals("database")) { + ps.print(database); + } else if (tok.equals("dbuser")) { + ps.print(dbuser); + } + if ((s.length() + 1) == n1) { + endOfline = true; + break; + } + s = s.substring(n1 + 1); + n = s.indexOf("{"); + } + + if (!endOfline) { + ps.println(s); + } + } + } + in.close(); + ps.close(); + } catch (Exception e) { + CMS.debug("DBSubsystem popuateDB: " + e.toString()); + throw new IOException( + "Problem of copying ldif file: " + filename); + } + ArrayList<String> errors = new ArrayList<String>(); + LDAPUtil.importLDIF(conn, filename, errors); + if (! errors.isEmpty()) { + CMS.debug("DatabasePanel: importLDIFS: LDAP Errors in importing " + filename); + for (String error: errors) { + CMS.debug(error); + } + } + } + } + + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore cs = CMS.getConfigStore(); + boolean hasErr = false; + + context.put("firsttime", "false"); + try { + @SuppressWarnings("unused") + String s = cs.getString("preop.database.removeData"); // check whether it's first time + } catch (Exception e) { + context.put("firsttime", "true"); + } + + String hostname1 = ""; + String portStr1 = ""; + String database1 = ""; + String masterPortStr = ""; + + try { + hostname1 = cs.getString("internaldb.ldapconn.host", ""); + portStr1 = cs.getString("internaldb.ldapconn.port", ""); + database1 = cs.getString("internaldb.database", ""); + masterPortStr = cs.getString("preop.internaldb.master.ldapconn.port", "0"); + } catch (Exception e) { + } + + try { + parseParameters(request, response, context); + } catch (IOException e) { + context.put("errorString", e.getMessage()); + cs.putString("preop.database.errorString", e.getMessage()); + context.put("updateStatus", "validate-failure"); + throw e; + } + + String hostname2 = (String) context.get("hostname"); + String portStr2 = (String) context.get("portStr"); + String database2 = (String) context.get("database"); + String basedn2 = (String) context.get("basedn"); + String binddn = (String) context.get("binddn"); + String secure = (String) context.get("secureConn"); + String masterReplicationPortStr = (String) context.get("masterReplicationPort"); + String cloneReplicationPortStr = (String) context.get("cloneReplicationPort"); + + cs.putString("internaldb.ldapconn.host", hostname2); + cs.putString("internaldb.ldapconn.port", portStr2); + cs.putString("internaldb.database", database2); + cs.putString("internaldb.basedn", basedn2); + cs.putString("internaldb.ldapauth.bindDN", binddn); + cs.putString("internaldb.ldapconn.secureConn", (secure.equals("on") ? "true" : "false")); + + int masterReplicationPort = 0; + if ((masterReplicationPortStr == null) || (masterReplicationPortStr.length() == 0)) { + masterReplicationPortStr = masterPortStr; + } + masterReplicationPort = Integer.parseInt(masterReplicationPortStr); + cs.putString("internaldb.ldapconn.masterReplicationPort", masterReplicationPortStr); + + int cloneReplicationPort = 0; + int port = Integer.parseInt(portStr2); + if ((cloneReplicationPortStr == null) || (cloneReplicationPortStr.length() == 0)) { + cloneReplicationPortStr = portStr2; + } + cloneReplicationPort = Integer.parseInt(cloneReplicationPortStr); + cs.putString("internaldb.ldapconn.cloneReplicationPort", cloneReplicationPortStr); + + String replicationSecurity = HttpInput.getString(request, "replicationSecurity"); + if ((cloneReplicationPort == port) && (secure.equals("true"))) { + replicationSecurity = "SSL"; + } else if (replicationSecurity == null) { + replicationSecurity = "None"; + } + cs.putString("internaldb.ldapconn.replicationSecurity", replicationSecurity); + + String remove = HttpInput.getID(request, "removeData"); + if (isPanelDone() && (remove == null || remove.equals(""))) { + /* if user submits the same data, they just want to skip + to the next panel, no database population is required. */ + if (hostname1.equals(hostname2) && + portStr1.equals(portStr2) && + database1.equals(database2)) { + context.put("updateStatus", "success"); + return; + } + } + + mServlet.cleanUpFromPanel(mServlet.getPanelNo(request)); + + try { + populateDB(request, context, (secure.equals("on") ? "true" : "false")); + } catch (IOException e) { + CMS.debug("DatabasePanel update: populateDB Exception: " + e.toString()); + context.put("updateStatus", "failure"); + throw e; + } catch (Exception e) { + CMS.debug("DatabasePanel update: populateDB Exception: " + e.toString()); + context.put("errorString", e.toString()); + cs.putString("preop.database.errorString", e.toString()); + context.put("updateStatus", "failure"); + throw new IOException(e.toString()); + } + + String bindpwd = HttpInput.getPassword(request, "__bindpwd"); + + /* BZ 430745 create password for replication manager */ + String replicationpwd = Integer.toString(new Random().nextInt()); + + IConfigStore psStore = null; + String passwordFile = null; + + try { + passwordFile = cs.getString("passwordFile"); + psStore = CMS.createFileConfigStore(passwordFile); + } catch (Exception e) { + CMS.debug("ConfigDatabaseServlet update: " + e.toString()); + context.put("updateStatus", "failure"); + throw new IOException(e.toString()); + } + psStore.putString("internaldb", bindpwd); + psStore.putString("replicationdb", replicationpwd); + cs.putString("preop.internaldb.replicationpwd", replicationpwd); + cs.putString("preop.database.removeData", "false"); + + try { + cs.commit(false); + psStore.commit(false); + CMS.reinit(IDBSubsystem.SUB_ID); + String type = cs.getString("cs.type", ""); + if (type.equals("CA")) + CMS.reinit(ICertificateAuthority.ID); + CMS.reinit(IAuthSubsystem.ID); + CMS.reinit(IAuthzSubsystem.ID); + CMS.reinit(IUGSubsystem.ID); + } catch (Exception e) { + CMS.debug("DatabasePanel update: " + e.toString()); + context.put("errorString", e.toString()); + cs.putString("preop.database.errorString", e.toString()); + context.put("updateStatus", "failure"); + throw new IOException(e.toString()); + } + + String select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + // always populate the index the last + try { + CMS.debug("Populating local indexes"); + LDAPConnection conn = getLocalLDAPConn(context, + (secure.equals("on") ? "true" : "false")); + importLDIFS("preop.internaldb.post_ldif", conn); + + /* For vlvtask, we need to check if the task has + been completed or not. Presence of nsTaskExitCode means task is complete + */ + String wait_dn = cs.getString("preop.internaldb.wait_dn", ""); + if (!wait_dn.equals("")) { + int i = 0; + LDAPEntry task = null; + boolean taskComplete = false; + CMS.debug("Checking wait_dn " + wait_dn); + do { + Thread.sleep(1000); + try { + task = conn.read(wait_dn, (String[]) null); + if (task != null) { + LDAPAttribute attr = task.getAttribute("nsTaskExitCode"); + if (attr != null) { + taskComplete = true; + String val = (String) attr.getStringValues().nextElement(); + if (val.compareTo("0") != 0) { + CMS.debug("Error in populating local indexes: nsTaskExitCode=" + val); + } + } + } + } catch (LDAPException le) { + CMS.debug("Still checking wait_dn '" + wait_dn + "' (" + le.toString() + ")"); + } catch (Exception e) { + CMS.debug("Still checking wait_dn '" + wait_dn + "' (" + e.toString() + ")."); + } + } while ((!taskComplete) && (i < 20)); + if (i < 20) { + CMS.debug("Done checking wait_dn " + wait_dn); + } else { + CMS.debug("Done checking wait_dn " + wait_dn + " due to timeout."); + } + } + + conn.disconnect(); + CMS.debug("Done populating local indexes"); + } catch (Exception e) { + CMS.debug("Populating index failure - " + e); + } + + // setup replication after indexes have been created + if (select.equals("clone")) { + CMS.debug("Start setting up replication."); + setupReplication(request, context, (secure.equals("on") ? "true" : "false"), + replicationSecurity, masterReplicationPort, cloneReplicationPort); + CMS.debug("Finish setting up replication."); + + try { + CMS.reinit(IDBSubsystem.SUB_ID); + String type = cs.getString("cs.type", ""); + if (type.equals("CA")) + CMS.reinit(ICertificateAuthority.ID); + CMS.reinit(IAuthSubsystem.ID); + CMS.reinit(IAuthzSubsystem.ID); + CMS.reinit(IUGSubsystem.ID); + } catch (Exception e) { + } + } + + if (hasErr == false) { + cs.putBoolean("preop.Database.done", true); + try { + cs.commit(false); + } catch (EBaseException e) { + CMS.debug( + "DatabasePanel: update() Exception caught at config commit: " + + e.toString()); + } + } + context.put("updateStatus", "success"); + } + + private void setupReplication(HttpServletRequest request, + Context context, String secure, String replicationSecurity, + int masterReplicationPort, int cloneReplicationPort) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + + String cstype = ""; + String machinename = ""; + String instanceId = ""; + try { + cstype = cs.getString("cs.type"); + cstype = toLowerCaseSubsystemType(cstype); + machinename = cs.getString("machineName", ""); + instanceId = cs.getString("instanceId", ""); + } catch (Exception e) { + } + + //setup replication agreement + String masterAgreementName = "masterAgreement1-" + machinename + "-" + instanceId; + cs.putString("internaldb.replication.master", masterAgreementName); + String cloneAgreementName = "cloneAgreement1-" + machinename + "-" + instanceId; + cs.putString("internaldb.replication.consumer", cloneAgreementName); + + try { + cs.commit(false); + } catch (Exception e) { + } + + // get connection to master + LDAPConnection masterConn = null; + ILdapConnFactory masterFactory = null; + try { + IConfigStore masterCfg = cs.getSubStore("preop.internaldb.master"); + masterFactory = CMS.getLdapBoundConnFactory(); + masterFactory.init(masterCfg); + masterConn = masterFactory.getConn(); + } catch (Exception e) { + CMS.debug("Failed to set up connection to master:" + e.toString()); + e.printStackTrace(); + throw new IOException("Failed to set up replication: No connection to master"); + } + + // get connection to replica + LDAPConnection replicaConn = null; + ILdapConnFactory replicaFactory = null; + try { + IConfigStore replicaCfg = cs.getSubStore("internaldb"); + replicaFactory = CMS.getLdapBoundConnFactory(); + replicaFactory.init(replicaCfg); + replicaConn = replicaFactory.getConn(); + } catch (Exception e) { + CMS.debug("Failed to set up connection to replica:" + e.toString()); + e.printStackTrace(); + throw new IOException("Failed to set up replication: No connection to replica"); + } + + String master_hostname = ""; + String master_replicationpwd = ""; + String replica_hostname = ""; + String replica_replicationpwd = ""; + + try { + master_hostname = cs.getString("preop.internaldb.master.ldapconn.host", ""); + master_replicationpwd = cs.getString("preop.internaldb.master.replication.password", ""); + replica_hostname = cs.getString("internaldb.ldapconn.host", ""); + replica_replicationpwd = cs.getString("preop.internaldb.replicationpwd", ""); + } catch (Exception e) { + } + + String basedn = ""; + try { + basedn = cs.getString("internaldb.basedn"); + } catch (Exception e) { + } + + try { + String suffix = cs.getString("internaldb.basedn", ""); + + String replicadn = "cn=replica,cn=\"" + suffix + "\",cn=mapping tree,cn=config"; + CMS.debug("DatabasePanel setupReplication: replicadn=" + replicadn); + + String masterBindUser = "Replication Manager " + masterAgreementName; + String cloneBindUser = "Replication Manager " + cloneAgreementName; + + createReplicationManager(masterConn, masterBindUser, master_replicationpwd); + createReplicationManager(replicaConn, cloneBindUser, replica_replicationpwd); + + String dir1 = getInstanceDir(masterConn); + createChangeLog(masterConn, dir1 + "/changelogs"); + + String dir2 = getInstanceDir(replicaConn); + createChangeLog(replicaConn, dir2 + "/changelogs"); + + int replicaId = cs.getInteger("dbs.beginReplicaNumber", 1); + + replicaId = enableReplication(replicadn, masterConn, masterBindUser, basedn, replicaId); + replicaId = enableReplication(replicadn, replicaConn, cloneBindUser, basedn, replicaId); + cs.putString("dbs.beginReplicaNumber", Integer.toString(replicaId)); + + CMS.debug("DatabasePanel setupReplication: Finished enabling replication"); + + createReplicationAgreement(replicadn, masterConn, masterAgreementName, + replica_hostname, cloneReplicationPort, replica_replicationpwd, basedn, + cloneBindUser, secure, replicationSecurity); + + createReplicationAgreement(replicadn, replicaConn, cloneAgreementName, + master_hostname, masterReplicationPort, master_replicationpwd, basedn, + masterBindUser, secure, replicationSecurity); + + // initialize consumer + initializeConsumer(replicadn, masterConn, masterAgreementName); + + while (!replicationDone(replicadn, masterConn, masterAgreementName)) { + CMS.debug("DatabasePanel setupReplication: Waiting for replication to complete"); + Thread.sleep(1000); + } + + String status = replicationStatus(replicadn, masterConn, masterAgreementName); + if (!status.startsWith("0 ")) { + CMS.debug("DatabasePanel setupReplication: consumer initialization failed. " + + status); + throw new IOException("consumer initialization failed. " + status); + } + + // remove master ldap password from password.conf (if present) + String passwordFile = cs.getString("passwordFile"); + IConfigStore psStore = CMS.createFileConfigStore(passwordFile); + psStore.remove("master_internaldb"); + psStore.commit(false); + + } catch (Exception e) { + CMS.debug("DatabasePanel setupReplication: " + e.toString()); + throw new IOException("Failed to setup the replication for cloning."); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + try { + initParams(request, context); + } catch (IOException e) { + } + context.put("title", "Database"); + context.put("panel", "admin/console/config/databasepanel.vm"); + } + + private void createReplicationManager(LDAPConnection conn, String bindUser, String pwd) + throws LDAPException { + LDAPAttributeSet attrs = null; + LDAPEntry entry = null; + String dn = "cn=" + bindUser + ",ou=csusers,cn=config"; + try { + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "person")); + attrs.add(new LDAPAttribute("userpassword", pwd)); + attrs.add(new LDAPAttribute("cn", bindUser)); + attrs.add(new LDAPAttribute("sn", "manager")); + entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { + CMS.debug("DatabasePanel createReplicationManager: Replication Manager has already used"); + try { + conn.delete(dn); + conn.add(entry); + } catch (LDAPException ee) { + CMS.debug("DatabasePanel createReplicationManager: " + ee.toString()); + } + return; + } else { + CMS.debug("DatabasePanel createReplicationManager: Failed to create replication manager. Exception: " + + e.toString()); + throw e; + } + } + + CMS.debug("DatabasePanel createReplicationManager: Successfully created Replication Manager"); + } + + private void createChangeLog(LDAPConnection conn, String dir) + throws LDAPException { + LDAPAttributeSet attrs = null; + LDAPEntry entry = null; + String dn = "cn=changelog5,cn=config"; + try { + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "extensibleObject")); + attrs.add(new LDAPAttribute("cn", "changelog5")); + attrs.add(new LDAPAttribute("nsslapd-changelogdir", dir)); + entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { + CMS.debug("DatabasePanel createChangeLog: Changelog entry has already used"); + /* leave it, dont delete it because it will have operation error + try { + conn.delete(dn); + conn.add(entry); + } catch (LDAPException ee) { + CMS.debug("DatabasePanel createChangeLog: "+ee.toString()); + } + */ + return; + } else { + CMS.debug("DatabasePanel createChangeLog: Failed to create changelog entry. Exception: " + e.toString()); + throw e; + } + } + + CMS.debug("DatabasePanel createChangeLog: Successfully create change log entry"); + } + + private int enableReplication(String replicadn, LDAPConnection conn, String bindUser, String basedn, int id) + throws LDAPException { + CMS.debug("DatabasePanel enableReplication: replicadn: " + replicadn); + LDAPAttributeSet attrs = null; + LDAPEntry entry = null; + try { + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "nsDS5Replica")); + attrs.add(new LDAPAttribute("objectclass", "extensibleobject")); + attrs.add(new LDAPAttribute("nsDS5ReplicaRoot", basedn)); + attrs.add(new LDAPAttribute("nsDS5ReplicaType", "3")); + attrs.add(new LDAPAttribute("nsDS5ReplicaBindDN", + "cn=" + bindUser + ",ou=csusers,cn=config")); + attrs.add(new LDAPAttribute("cn", "replica")); + attrs.add(new LDAPAttribute("nsDS5ReplicaId", Integer.toString(id))); + attrs.add(new LDAPAttribute("nsds5flags", "1")); + entry = new LDAPEntry(replicadn, attrs); + conn.add(entry); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { + /* BZ 470918 -we cant just add the new dn. We need to do a replace instead + * until the DS code is fixed */ + CMS.debug("DatabasePanel enableReplication: " + replicadn + " has already been used"); + + try { + entry = conn.read(replicadn); + LDAPAttribute attr = entry.getAttribute("nsDS5ReplicaBindDN"); + attr.addValue("cn=" + bindUser + ",ou=csusers,cn=config"); + LDAPModification mod = new LDAPModification(LDAPModification.REPLACE, attr); + conn.modify(replicadn, mod); + } catch (LDAPException ee) { + CMS.debug("DatabasePanel enableReplication: Failed to modify " + + replicadn + " entry. Exception: " + e.toString()); + } + return id; + } else { + CMS.debug("DatabasePanel enableReplication: Failed to create " + + replicadn + " entry. Exception: " + e.toString()); + return id; + } + } + + CMS.debug("DatabasePanel enableReplication: Successfully create " + replicadn + " entry."); + return id + 1; + } + + private void createReplicationAgreement(String replicadn, + LDAPConnection conn, String name, String replicahost, int replicaport, + String replicapwd, String basedn, String bindUser, String secure, String replicationSecurity) + throws LDAPException { + String dn = "cn=" + name + "," + replicadn; + CMS.debug("DatabasePanel createReplicationAgreement: dn: " + dn); + LDAPEntry entry = null; + LDAPAttributeSet attrs = null; + try { + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", + "nsds5replicationagreement")); + attrs.add(new LDAPAttribute("cn", name)); + attrs.add(new LDAPAttribute("nsDS5ReplicaRoot", basedn)); + attrs.add(new LDAPAttribute("nsDS5ReplicaHost", replicahost)); + + attrs.add(new LDAPAttribute("nsDS5ReplicaPort", "" + replicaport)); + attrs.add(new LDAPAttribute("nsDS5ReplicaBindDN", + "cn=" + bindUser + ",ou=csusers,cn=config")); + attrs.add(new LDAPAttribute("nsDS5ReplicaBindMethod", "Simple")); + attrs.add(new LDAPAttribute("nsds5replicacredentials", replicapwd)); + + if (replicationSecurity.equals("SSL")) { + attrs.add(new LDAPAttribute("nsDS5ReplicaTransportInfo", "SSL")); + } else if (replicationSecurity.equals("TLS")) { + attrs.add(new LDAPAttribute("nsDS5ReplicaTransportInfo", "TLS")); + } + + CMS.debug("About to set description attr to " + name); + attrs.add(new LDAPAttribute("description", name)); + + entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { + CMS.debug("DatabasePanel createReplicationAgreement: " + dn + " has already used"); + try { + conn.delete(dn); + } catch (LDAPException ee) { + CMS.debug("DatabasePanel createReplicationAgreement: " + ee.toString()); + throw ee; + } + + try { + conn.add(entry); + } catch (LDAPException ee) { + CMS.debug("DatabasePanel createReplicationAgreement: " + ee.toString()); + throw ee; + } + } else { + CMS.debug("DatabasePanel createReplicationAgreement: Failed to create " + + dn + " entry. Exception: " + e.toString()); + throw e; + } + } + + CMS.debug("DatabasePanel createReplicationAgreement: Successfully create replication agreement " + name); + } + + private void initializeConsumer(String replicadn, LDAPConnection conn, + String name) { + String dn = "cn=" + name + "," + replicadn; + CMS.debug("DatabasePanel initializeConsumer: initializeConsumer dn: " + dn); + CMS.debug("DatabasePanel initializeConsumer: initializeConsumer host: " + + conn.getHost() + " port: " + conn.getPort()); + try { + LDAPAttribute attr = new LDAPAttribute("nsds5beginreplicarefresh", + "start"); + LDAPModification mod = new LDAPModification( + LDAPModification.REPLACE, attr); + CMS.debug("DatabasePanel initializeConsumer: start modifying"); + conn.modify(dn, mod); + CMS.debug("DatabasePanel initializeConsumer: Finish modification."); + } catch (LDAPException e) { + CMS.debug("DatabasePanel initializeConsumer: Failed to modify " + dn + " entry. Exception: " + e.toString()); + return; + } catch (Exception e) { + CMS.debug("DatabasePanel initializeConsumer: exception " + e); + } + + try { + CMS.debug("DatabasePanel initializeConsumer: thread sleeping for 5 seconds."); + Thread.sleep(5000); + CMS.debug("DatabasePanel initializeConsumer: finish sleeping."); + } catch (InterruptedException ee) { + CMS.debug("DatabasePanel initializeConsumer: exception: " + ee.toString()); + } + + CMS.debug("DatabasePanel initializeConsumer: Successfully initialize consumer"); + } + + private boolean replicationDone(String replicadn, LDAPConnection conn, String name) + throws IOException { + String dn = "cn=" + name + "," + replicadn; + String filter = "(objectclass=*)"; + String[] attrs = { "nsds5beginreplicarefresh" }; + + CMS.debug("DatabasePanel replicationDone: dn: " + dn); + try { + LDAPSearchResults results = conn.search(dn, LDAPConnection.SCOPE_BASE, filter, + attrs, true); + + int count = results.getCount(); + if (count < 1) { + throw new IOException("Replication entry not found"); + } + + LDAPEntry entry = results.next(); + LDAPAttribute refresh = entry.getAttribute("nsds5beginreplicarefresh"); + if (refresh == null) { + return true; + } + return false; + } catch (Exception e) { + CMS.debug("DatabasePanel replicationDone: exception " + e); + throw new IOException("Exception in replicationDone: " + e); + } + } + + private String replicationStatus(String replicadn, LDAPConnection conn, String name) + throws IOException { + String dn = "cn=" + name + "," + replicadn; + String filter = "(objectclass=*)"; + String[] attrs = { "nsds5replicalastinitstatus" }; + + CMS.debug("DatabasePanel replicationStatus: dn: " + dn); + try { + LDAPSearchResults results = conn.search(dn, LDAPConnection.SCOPE_BASE, filter, + attrs, false); + + int count = results.getCount(); + if (count < 1) { + throw new IOException("Replication entry not found"); + } + + LDAPEntry entry = results.next(); + LDAPAttribute attr = entry.getAttribute("nsds5replicalastinitstatus"); + if (attr != null) { + @SuppressWarnings("unchecked") + Enumeration<String> valsInAttr = attr.getStringValues(); + if (valsInAttr.hasMoreElements()) { + return valsInAttr.nextElement(); + } else { + throw new IOException("No value returned for nsds5replicalastinitstatus"); + } + } else { + throw new IOException("nsDS5ReplicaLastInitStatus is null."); + } + } catch (Exception e) { + CMS.debug("DatabasePanel replicationStatus: exception " + e); + throw new IOException("Exception in replicationStatus: " + e); + } + } + + private String getInstanceDir(LDAPConnection conn) { + String instancedir = ""; + try { + String filter = "(objectclass=*)"; + String[] attrs = { "nsslapd-directory" }; + LDAPSearchResults results = + conn.search("cn=config,cn=ldbm database,cn=plugins,cn=config", LDAPv3.SCOPE_SUB, + filter, attrs, false); + + while (results.hasMoreElements()) { + LDAPEntry entry = results.next(); + String dn = entry.getDN(); + CMS.debug("DatabasePanel getInstanceDir: DN for storing nsslapd-directory: " + dn); + LDAPAttributeSet entryAttrs = entry.getAttributeSet(); + @SuppressWarnings("unchecked") + Enumeration<LDAPAttribute> attrsInSet = entryAttrs.getAttributes(); + while (attrsInSet.hasMoreElements()) { + LDAPAttribute nextAttr = attrsInSet.nextElement(); + String attrName = nextAttr.getName(); + CMS.debug("DatabasePanel getInstanceDir: attribute name: " + attrName); + @SuppressWarnings("unchecked") + Enumeration<String> valsInAttr = nextAttr.getStringValues(); + while (valsInAttr.hasMoreElements()) { + String nextValue = valsInAttr.nextElement(); + if (attrName.equalsIgnoreCase("nsslapd-directory")) { + CMS.debug("DatabasePanel getInstanceDir: instanceDir=" + nextValue); + return nextValue.substring(0, nextValue.lastIndexOf("/db")); + } + } + } + } + } catch (LDAPException e) { + CMS.debug("DatabasePanel getInstanceDir: Error in retrieving the instance directory. Exception: " + + e.toString()); + } + + return instancedir; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/DatabaseServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/DatabaseServlet.java new file mode 100644 index 000000000..c44f61130 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/DatabaseServlet.java @@ -0,0 +1,49 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +public class DatabaseServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = 6474664942834474385L; + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + Template template = null; + + try { + context.put("name", "Velocity Test"); + template = Velocity.getTemplate("admin/console/config/database.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java new file mode 100644 index 000000000..c6db8a8b7 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java @@ -0,0 +1,236 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.net.URLEncoder; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.util.CertPrettyPrint; +import netscape.security.x509.X509CertImpl; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class DisplayCertChainPanel extends WizardPanelBase { + + public DisplayCertChainPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Display Certificate Chain"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Display Certificate Chain"); + setId(id); + } + + public boolean isSubPanel() { + return true; + } + + public boolean isPanelDone() { + return true; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + return set; + } + + public void cleanUp() throws IOException { + } + + /** + * Should we skip this panel for the configuration. + */ + public boolean shouldSkip() { + CMS.debug("DisplayCertChainPanel: should skip"); + + IConfigStore cs = CMS.getConfigStore(); + // if we are root, no need to get the certificate chain. + + try { + String select = cs.getString("securitydomain.select", ""); + String type = cs.getString("preop.subsystem.select", ""); + String hierarchy = cs.getString("preop.hierarchy.select", ""); + + if (getId().equals("hierarchy") && hierarchy.equals("root")) + return true; + + if (select.equals("new")) { + return true; + } + + if (type.equals("new") && getId().equals("clone")) + return true; + + if (type.equals("clone") && getId().equals("ca")) + return true; + } catch (EBaseException e) { + } + + return false; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("DisplayCertChainPanel: display"); + + // update session id + String session_id = request.getParameter("session_id"); + if (session_id != null) { + CMS.debug("DisplayCertChainPanel setting session id."); + CMS.setConfigSDSessionId(session_id); + } + + String type = getId(); + + IConfigStore cs = CMS.getConfigStore(); + String certChainConfigName = "preop." + type + ".certchain.size"; + String certchain_size = ""; + + try { + certchain_size = cs.getString(certChainConfigName, ""); + } catch (Exception e) { + } + + int size = 0; + Vector<String> v = new Vector<String>(); + + if (!certchain_size.equals("")) { + try { + size = Integer.parseInt(certchain_size); + } catch (Exception e) { + } + for (int i = 0; i < size; i++) { + certChainConfigName = "preop." + type + ".certchain." + i; + try { + String c = cs.getString(certChainConfigName, ""); + byte[] b_c = CryptoUtil.base64Decode(c); + CertPrettyPrint pp = new CertPrettyPrint( + new X509CertImpl(b_c)); + + v.addElement(pp.toString(Locale.getDefault())); + } catch (Exception e) { + } + } + } + + if (getId().equals("securitydomain")) { + context.put("panelid", "securitydomain"); + context.put("panelname", "Security Domain Trust Verification"); + } else { + context.put("panelid", "other"); + context.put("panelname", "Subsystem Trust Verification"); + } + context.put("title", "Display Certificate Chain"); + context.put("panel", "admin/console/config/displaycertchainpanel.vm"); + context.put("errorString", ""); + context.put("certchain", v); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + importCertChain(getId()); + + if (getId().equals("securitydomain")) { + int panel = getPanelNo() + 1; + IConfigStore cs = CMS.getConfigStore(); + try { + String sd_hostname = cs.getString("securitydomain.host", ""); + int sd_port = cs.getInteger("securitydomain.httpsadminport", -1); + String cs_hostname = cs.getString("machineName", ""); + int cs_port = cs.getInteger("pkicreate.admin_secure_port", -1); + String subsystem = cs.getString("cs.type", ""); + String urlVal = + "https://" + + cs_hostname + ":" + cs_port + "/" + toLowerCaseSubsystemType(subsystem) + + "/admin/console/config/wizard?p=" + panel + "&subsystem=" + subsystem; + String encodedValue = URLEncoder.encode(urlVal, "UTF-8"); + String sdurl = + "https://" + + sd_hostname + ":" + sd_port + "/ca/admin/ca/securityDomainLogin?url=" + encodedValue; + response.sendRedirect(sdurl); + + // The user previously specified the CA Security Domain's + // SSL Admin port in the "Security Domain Panel"; + // now retrieve this specified CA Security Domain's + // non-SSL EE, SSL Agent, and SSL EE ports: + cs.putString("securitydomain.httpport", + getSecurityDomainPort(cs, "UnSecurePort")); + cs.putString("securitydomain.httpsagentport", + getSecurityDomainPort(cs, "SecureAgentPort")); + cs.putString("securitydomain.httpseeport", + getSecurityDomainPort(cs, "SecurePort")); + } catch (Exception ee) { + CMS.debug("DisplayCertChainPanel Exception=" + ee.toString()); + } + } + context.put("updateStatus", "success"); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + /* This should never be called */ + context.put("title", "Display Certificate Chain"); + context.put("panel", "admin/console/config/displaycertchainpanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/DisplayServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/DisplayServlet.java new file mode 100644 index 000000000..3bb8c73c8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/DisplayServlet.java @@ -0,0 +1,49 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +public class DisplayServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = -8753831516572779596L; + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + Template template = null; + + try { + String tmpl = request.getParameter("t"); + + template = Velocity.getTemplate(tmpl); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java new file mode 100644 index 000000000..6d0e92618 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java @@ -0,0 +1,897 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.math.BigInteger; +import java.net.URLEncoder; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPModification; +import netscape.security.x509.X509CertImpl; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.usrgrp.EUsrGrpException; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.password.IPasswordStore; +import com.netscape.cmsutil.util.Cert; +import com.netscape.cmsutil.util.Utils; + +public class DonePanel extends WizardPanelBase { + + public static final BigInteger BIG_ZERO = new BigInteger("0"); + public static final Long MINUS_ONE = Long.valueOf(-1); + public static final String RESTART_SERVER_AFTER_CONFIGURATION = + "restart_server_after_configuration"; + public static final String PKI_SECURITY_DOMAIN = "pki_security_domain"; + + public DonePanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Done"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Done"); + setId(id); + } + + public boolean hasSubPanel() { + return false; + } + + public void cleanUp() throws IOException { + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + private LDAPConnection getLDAPConn(Context context) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + + String host = ""; + String port = ""; + String pwd = null; + String binddn = ""; + String security = ""; + + IPasswordStore pwdStore = CMS.getPasswordStore(); + + if (pwdStore != null) { + CMS.debug("DonePanel: getLDAPConn: password store available"); + pwd = pwdStore.getPassword("internaldb"); + } + + if (pwd == null) { + throw new IOException("DonePanel: Failed to obtain password from password store"); + } + + try { + host = cs.getString("internaldb.ldapconn.host"); + port = cs.getString("internaldb.ldapconn.port"); + binddn = cs.getString("internaldb.ldapauth.bindDN"); + security = cs.getString("internaldb.ldapconn.secureConn"); + } catch (Exception e) { + CMS.debug("DonePanel: getLDAPConn" + e.toString()); + throw new IOException( + "Failed to retrieve LDAP information from CS.cfg."); + } + + int p = -1; + + try { + p = Integer.parseInt(port); + } catch (Exception e) { + CMS.debug("DonePanel getLDAPConn: " + e.toString()); + throw new IOException("Port is not valid"); + } + + LDAPConnection conn = null; + if (security.equals("true")) { + CMS.debug("DonePanel getLDAPConn: creating secure (SSL) connection for internal ldap"); + conn = new LDAPConnection(CMS.getLdapJssSSLSocketFactory()); + } else { + CMS.debug("DonePanel getLDAPConn: creating non-secure (non-SSL) connection for internal ldap"); + conn = new LDAPConnection(); + } + + CMS.debug("DonePanel connecting to " + host + ":" + p); + try { + conn.connect(host, p, binddn, pwd); + } catch (LDAPException e) { + CMS.debug("DonePanel getLDAPConn: " + e.toString()); + throw new IOException("Failed to connect to the internal database."); + } + + return conn; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("DonePanel: display()"); + + // update session id + String session_id = request.getParameter("session_id"); + if (session_id != null) { + CMS.debug("NamePanel setting session id."); + CMS.setConfigSDSessionId(session_id); + } + + IConfigStore cs = CMS.getConfigStore(); + String ownport = CMS.getEENonSSLPort(); + String ownsport = CMS.getEESSLPort(); + String owneeclientauthsport = CMS.getEEClientAuthSSLPort(); + String ownhost = CMS.getEESSLHost(); + String ownagentsport = CMS.getAgentPort(); + String ownagenthost = CMS.getAgentHost(); + String ownadminsport = CMS.getAdminPort(); + String ownadminhost = CMS.getAdminHost(); + String select = ""; + + String type = ""; + String instanceId = ""; + String instanceRoot = ""; + String systemdService = ""; + try { + type = cs.getString("cs.type", ""); + instanceId = cs.getString("instanceId"); + instanceRoot = cs.getString("instanceRoot"); + select = cs.getString("preop.subsystem.select", ""); + systemdService = cs.getString("pkicreate.systemd.servicename", ""); + } catch (Exception e) { + } + + String initDaemon = ""; + if (type.equals("CA")) { + initDaemon = "pki-cad"; + } else if (type.equals("KRA")) { + initDaemon = "pki-krad"; + } else if (type.equals("OCSP")) { + initDaemon = "pki-ocspd"; + } else if (type.equals("TKS")) { + initDaemon = "pki-tksd"; + } + String os = System.getProperty("os.name"); + if (os.equalsIgnoreCase("Linux")) { + if (!systemdService.equals("")) { + context.put("initCommand", "/bin/systemctl"); + context.put("instanceId", systemdService); + } else { + context.put("initCommand", "/sbin/service " + initDaemon); + context.put("instanceId", instanceId); + } + } else { + /* default case: e. g. - ( os.equalsIgnoreCase( "SunOS" ) */ + context.put("initCommand", "/etc/init.d/" + initDaemon); + context.put("instanceId", instanceId); + } + context.put("title", "Done"); + context.put("panel", "admin/console/config/donepanel.vm"); + context.put("host", ownadminhost); + context.put("port", ownadminsport); + String subsystemType = toLowerCaseSubsystemType(type); + context.put("systemType", subsystemType); + + try { + int state = cs.getInteger("cs.state"); + if (state == 1) { + context.put("csstate", "1"); + return; + } else + context.put("csstate", "0"); + + } catch (Exception e) { + } + + String sd_agent_port = ""; + String sd_admin_port = ""; + String sd_host = ""; + String ca_host = ""; + try { + sd_host = cs.getString("securitydomain.host", ""); + sd_agent_port = cs.getString("securitydomain.httpsagentport", ""); + sd_admin_port = cs.getString("securitydomain.httpsadminport", ""); + ca_host = cs.getString("preop.ca.hostname", ""); + } catch (Exception e) { + } + + if (ca_host.equals("")) + context.put("externalCA", "true"); + else + context.put("externalCA", "false"); + + // update security domain + String sdtype = ""; + String subsystemName = ""; + try { + sdtype = cs.getString("securitydomain.select", ""); + subsystemName = cs.getString("preop.subsystem.name", ""); + } catch (Exception e) { + } + + boolean cloneMaster = false; + + if (select.equals("clone") && type.equalsIgnoreCase("CA") && isSDHostDomainMaster(cs)) { + cloneMaster = true; + CMS.debug("Cloning a domain master"); + } + + String s = getSubsystemNodeName(type); + if (sdtype.equals("new")) { + try { + LDAPConnection conn = getLDAPConn(context); + + String basedn = cs.getString("internaldb.basedn"); + String secdomain = cs.getString("securitydomain.name"); + + try { + // Create security domain ldap entry + String dn = "ou=Security Domain," + basedn; + CMS.debug("DonePanel: creating ldap entry : " + dn); + + LDAPEntry entry = null; + LDAPAttributeSet attrs = null; + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "pkiSecurityDomain")); + if (secdomain.equals("")) { + // this should not happen - just in case + CMS.debug("DonePanel display(): Security domain is an empty string!"); + throw new IOException("Security domain is an empty string!"); + } else { + attrs.add(new LDAPAttribute("name", secdomain)); + } + attrs.add(new LDAPAttribute("ou", "Security Domain")); + entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } catch (Exception e) { + CMS.debug("Unable to create security domain"); + throw e; + } + + try { + // create list containers + String clist[] = { "CAList", "OCSPList", "KRAList", "RAList", "TKSList", "TPSList" }; + for (int i = 0; i < clist.length; i++) { + LDAPEntry entry = null; + LDAPAttributeSet attrs = null; + String dn = "cn=" + clist[i] + ",ou=Security Domain," + basedn; + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "pkiSecurityGroup")); + attrs.add(new LDAPAttribute("cn", clist[i])); + entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } + } catch (Exception e) { + CMS.debug("Unable to create security domain list groups"); + throw e; + } + + try { + // Add this host (only CA can create new domain) + String cn = ownhost + ":" + ownadminsport; + String dn = "cn=" + cn + ",cn=CAList,ou=Security Domain," + basedn; + LDAPEntry entry = null; + LDAPAttributeSet attrs = null; + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "pkiSubsystem")); + attrs.add(new LDAPAttribute("Host", ownhost)); + attrs.add(new LDAPAttribute("SecurePort", ownsport)); + attrs.add(new LDAPAttribute("SecureAgentPort", + ownagentsport)); + attrs.add(new LDAPAttribute("SecureAdminPort", + ownadminsport)); + if (owneeclientauthsport != null) { + attrs.add(new LDAPAttribute("SecureEEClientAuthPort", + owneeclientauthsport)); + } + attrs.add(new LDAPAttribute("UnSecurePort", ownport)); + attrs.add(new LDAPAttribute("Clone", "FALSE")); + attrs.add(new LDAPAttribute("SubsystemName", subsystemName)); + attrs.add(new LDAPAttribute("cn", cn)); + attrs.add(new LDAPAttribute("DomainManager", "TRUE")); + entry = new LDAPEntry(dn, attrs); + conn.add(entry); + } catch (Exception e) { + CMS.debug("Unable to create host entry in security domain"); + throw e; + } + CMS.debug("DonePanel display: finish updating domain info"); + conn.disconnect(); + } catch (Exception e) { + CMS.debug("DonePanel display: " + e.toString()); + } + + int sd_admin_port_int = -1; + try { + sd_admin_port_int = Integer.parseInt(sd_admin_port); + } catch (Exception e) { + } + + try { + // Fetch the "new" security domain and display it + CMS.debug("Dump contents of new Security Domain . . ."); + @SuppressWarnings("unused") + String c = getDomainXML(sd_host, sd_admin_port_int, true); + } catch (Exception e) { + } + + // Since this instance is a new Security Domain, + // create an empty file to designate this fact. + String security_domain = instanceRoot + "/conf/" + + PKI_SECURITY_DOMAIN; + if (!Utils.isNT()) { + Utils.exec("touch " + security_domain); + Utils.exec("chmod 00660 " + security_domain); + } + + } else { //existing domain + int sd_agent_port_int = -1; + int sd_admin_port_int = -1; + try { + sd_agent_port_int = Integer.parseInt(sd_agent_port); + sd_admin_port_int = Integer.parseInt(sd_admin_port); + } catch (Exception e) { + } + + try { + String cloneStr = ""; + if (select.equals("clone")) + cloneStr = "&clone=true"; + else + cloneStr = "&clone=false"; + + String domainMasterStr = ""; + if (cloneMaster) + domainMasterStr = "&dm=true"; + else + domainMasterStr = "&dm=false"; + String eecaStr = ""; + if (owneeclientauthsport != null) + eecaStr = "&eeclientauthsport=" + owneeclientauthsport; + + updateDomainXML(sd_host, sd_agent_port_int, true, + "/ca/agent/ca/updateDomainXML", + "list=" + s + + "&type=" + type + + "&host=" + ownhost + + "&name=" + subsystemName + + "&sport=" + ownsport + + domainMasterStr + + cloneStr + + "&agentsport=" + ownagentsport + + "&adminsport=" + ownadminsport + + eecaStr + + "&httpport=" + ownport); + + // Fetch the "updated" security domain and display it + CMS.debug("Dump contents of updated Security Domain . . ."); + @SuppressWarnings("unused") + String c = getDomainXML(sd_host, sd_admin_port_int, true); + } catch (Exception e) { + context.put("errorString", "Failed to update the security domain on the domain master."); + //return; + } + } + + // add service.securityDomainPort to CS.cfg in case pkiremove + // needs to remove system reference from the security domain + try { + cs.putString("service.securityDomainPort", ownagentsport); + cs.putString("securitydomain.store", "ldap"); + cs.commit(false); + } catch (Exception e) { + CMS.debug("DonePanel: exception in adding service.securityDomainPort to CS.cfg" + e); + } + + // need to push connector information to the CA + if (type.equals("KRA") && !ca_host.equals("")) { + try { + updateConnectorInfo(ownagenthost, ownagentsport); + } catch (IOException e) { + context.put("errorString", "Failed to update connector information."); + return; + } + setupClientAuthUser(); + } // if KRA + + // import the CA certificate into the OCSP + // configure the CRL Publishing to OCSP in CA + if (type.equals("OCSP") && !ca_host.equals("")) { + try { + CMS.reinit(IOCSPAuthority.ID); + importCACertToOCSP(); + } catch (Exception e) { + CMS.debug("DonePanel display: Failed to import the CA certificate into OCSP."); + } + + try { + updateOCSPConfig(response); + } catch (Exception e) { + CMS.debug("DonePanel display: Failed to update OCSP information in CA."); + } + + setupClientAuthUser(); + } + + if (!select.equals("clone")) { + if (type.equals("CA") || type.equals("KRA")) { + String endRequestNumStr = ""; + String endSerialNumStr = ""; + + try { + endRequestNumStr = cs.getString("dbs.endRequestNumber", ""); + endSerialNumStr = cs.getString("dbs.endSerialNumber", ""); + BigInteger endRequestNum = new BigInteger(endRequestNumStr); + BigInteger endSerialNum = new BigInteger(endSerialNumStr); + BigInteger oneNum = new BigInteger("1"); + + // update global next range entries + LDAPConnection conn = getLDAPConn(context); + String basedn = cs.getString("internaldb.basedn"); + + String serialdn = ""; + if (type.equals("CA")) { + serialdn = "ou=certificateRepository,ou=" + type.toLowerCase() + "," + basedn; + } else { + serialdn = "ou=keyRepository,ou=" + type.toLowerCase() + "," + basedn; + } + LDAPAttribute attrSerialNextRange = + new LDAPAttribute("nextRange", endSerialNum.add(oneNum).toString()); + LDAPModification serialmod = new LDAPModification(LDAPModification.REPLACE, attrSerialNextRange); + conn.modify(serialdn, serialmod); + + String requestdn = "ou=" + type.toLowerCase() + ",ou=requests," + basedn; + LDAPAttribute attrRequestNextRange = + new LDAPAttribute("nextRange", endRequestNum.add(oneNum).toString()); + LDAPModification requestmod = new LDAPModification(LDAPModification.REPLACE, attrRequestNextRange); + conn.modify(requestdn, requestmod); + + conn.disconnect(); + } catch (Exception e) { + CMS.debug("Unable to update global next range numbers: " + e); + } + } + } + + if (cloneMaster) { + // cloning a domain master CA, the clone is also master of its domain + try { + cs.putString("securitydomain.host", ownhost); + cs.putString("securitydomain.httpport", ownport); + cs.putString("securitydomain.httpsadminport", ownadminsport); + cs.putString("securitydomain.httpsagentport", ownagentsport); + cs.putString("securitydomain.httpseeport", ownsport); + cs.putString("securitydomain.select", "new"); + } catch (Exception e) { + CMS.debug("Caught exception trying to save security domain parameters for clone of a domain master"); + } + } + + String dbuser = null; + try { + dbuser = cs.getString("cs.type") + "-" + cs.getString("machineName") + "-" + cs.getString("service.securePort"); + if (! sdtype.equals("new")) { + setupDBUser(dbuser); + } + IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID)); + IUser user = system.getUser(dbuser); + system.addCertSubjectDN(user); + } catch (Exception e) { + e.printStackTrace(); + CMS.debug("Unable to create or update dbuser" + e); + } + + cs.putInteger("cs.state", 1); + try { + // save variables needed for cloning and remove preop + String list = cs.getString("preop.cert.list", ""); + StringTokenizer st = new StringTokenizer(list, ","); + + while (st.hasMoreTokens()) { + String ss = st.nextToken(); + if (ss.equals("sslserver")) + continue; + cs.putString("cloning." + ss + ".nickname", cs.getString("preop.cert." + ss + ".nickname", "")); + cs.putString("cloning." + ss + ".dn", cs.getString("preop.cert." + ss + ".dn", "")); + cs.putString("cloning." + ss + ".keytype", cs.getString("preop.cert." + ss + ".keytype", "")); + cs.putString("cloning." + ss + ".keyalgorithm", cs.getString("preop.cert." + ss + ".keyalgorithm", "")); + cs.putString("cloning." + ss + ".privkey.id", cs.getString("preop.cert." + ss + ".privkey.id", "")); + cs.putString("cloning." + ss + ".pubkey.exponent", + cs.getString("preop.cert." + ss + ".pubkey.exponent", "")); + cs.putString("cloning." + ss + ".pubkey.modulus", + cs.getString("preop.cert." + ss + ".pubkey.modulus", "")); + cs.putString("cloning." + ss + ".pubkey.encoded", + cs.getString("preop.cert." + ss + ".pubkey.encoded", "")); + } + cs.putString("cloning.module.token", cs.getString("preop.module.token", "")); + cs.putString("cloning.list", list); + + // more cloning variables needed for non-ca clones + + if (!type.equals("CA")) { + String val = cs.getString("preop.ca.hostname", ""); + if (val.compareTo("") != 0) + cs.putString("cloning.ca.hostname", val); + + val = cs.getString("preop.ca.httpport", ""); + if (val.compareTo("") != 0) + cs.putString("cloning.ca.httpport", val); + + val = cs.getString("preop.ca.httpsport", ""); + if (val.compareTo("") != 0) + cs.putString("cloning.ca.httpsport", val); + + val = cs.getString("preop.ca.list", ""); + if (val.compareTo("") != 0) + cs.putString("cloning.ca.list", val); + + val = cs.getString("preop.ca.pkcs7", ""); + if (val.compareTo("") != 0) + cs.putString("cloning.ca.pkcs7", val); + + val = cs.getString("preop.ca.type", ""); + if (val.compareTo("") != 0) + cs.putString("cloning.ca.type", val); + } + + // save EC type for sslserver cert (if present) + cs.putString("jss.ssl.sslserver.ectype", cs.getString("preop.cert.sslserver.ec.type", "ECDHE")); + + cs.removeSubStore("preop"); + cs.commit(false); + + // Create an empty file that designates the fact that although + // this server instance has been configured, it has NOT yet + // been restarted! + String restart_server = instanceRoot + "/conf/" + + RESTART_SERVER_AFTER_CONFIGURATION; + if (!Utils.isNT()) { + Utils.exec("touch " + restart_server); + Utils.exec("chmod 00660 " + restart_server); + } + + } catch (Exception e) { + CMS.debug("Caught exception saving preop variables: " + e); + } + + context.put("csstate", "1"); + } + + private void setupClientAuthUser() { + IConfigStore cs = CMS.getConfigStore(); + + // retrieve CA subsystem certificate from the CA + IUGSubsystem system = + (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID)); + String id = ""; + try { + String b64 = getCASubsystemCert(); + if (b64 != null) { + int num = cs.getInteger("preop.subsystem.count", 0); + id = getCAUserId(); + num++; + cs.putInteger("preop.subsystem.count", num); + cs.putInteger("subsystem.count", num); + IUser user = system.createUser(id); + user.setFullName(id); + user.setEmail(""); + user.setPassword(""); + user.setUserType("agentType"); + user.setState("1"); + user.setPhone(""); + X509CertImpl[] certs = new X509CertImpl[1]; + certs[0] = new X509CertImpl(CMS.AtoB(b64)); + user.setX509Certificates(certs); + system.addUser(user); + CMS.debug("DonePanel display: successfully add the user"); + system.addUserCert(user); + CMS.debug("DonePanel display: successfully add the user certificate"); + cs.commit(false); + } + } catch (Exception e) { + } + + try { + String groupName = "Trusted Managers"; + IGroup group = system.getGroupFromName(groupName); + if (!group.isMember(id)) { + group.addMemberName(id); + system.modifyGroup(group); + CMS.debug("DonePanel display: successfully added the user to the group."); + } + } catch (Exception e) { + } + } + + private void setupDBUser(String dbuser) throws CertificateException, EUsrGrpException, LDAPException { + IUGSubsystem system = + (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID)); + + String b64 = getSubsystemCert(); + if (b64 == null) { + CMS.debug("DonePanel setupDBUser: failed to fetch subsystem cert"); + return; + } + + IUser user = system.createUser(dbuser); + user.setFullName(dbuser); + user.setEmail(""); + user.setPassword(""); + user.setUserType("agentType"); + user.setState("1"); + user.setPhone(""); + X509CertImpl[] certs = new X509CertImpl[1]; + certs[0] = new X509CertImpl(CMS.AtoB(b64)); + user.setX509Certificates(certs); + system.addUser(user); + CMS.debug("DonePanel setupDBUser: successfully add the user"); + system.addUserCert(user); + CMS.debug("DonePanel setupDBUser: successfully add the user certificate"); + } + + private String getSubsystemCert() { + IConfigStore cs = CMS.getConfigStore(); + String nickname = ""; + try { + nickname = cs.getString("preop.cert.subsystem.nickname", ""); + String tokenname = cs.getString("preop.module.token", ""); + if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token") + && !tokenname.equals("")) + nickname = tokenname + ":" + nickname; + } catch (Exception e) { + } + + CMS.debug("DonePanel getSubsystemCert: nickname=" + nickname); + String s = null; + try { + CryptoManager cm = CryptoManager.getInstance(); + org.mozilla.jss.crypto.X509Certificate cert = cm.findCertByNickname(nickname); + + if (cert == null) { + CMS.debug("DonePanel getSubsystemCert: subsystem cert is null"); + return null; + } + + byte[] bytes = cert.getEncoded(); + s = CryptoUtil.normalizeCertStr(CryptoUtil.base64Encode(bytes)); + } catch (Exception e) { + CMS.debug("DonePanel getSubsystemCert: exception: " + e.toString()); + } + return s; + } + + private void updateOCSPConfig(HttpServletResponse response) + throws IOException { + IConfigStore config = CMS.getConfigStore(); + String cahost = ""; + int caport = -1; + + try { + cahost = config.getString("preop.ca.hostname", ""); + caport = config.getInteger("preop.ca.httpsport", -1); + } catch (Exception e) { + } + + String ocsphost = CMS.getAgentHost(); + int ocspport = Integer.parseInt(CMS.getAgentPort()); + String session_id = CMS.getConfigSDSessionId(); + String content = "xmlOutput=true&sessionID=" + session_id + "&ocsp_host=" + ocsphost + "&ocsp_port=" + ocspport; + + updateOCSPConfig(cahost, caport, true, content, response); + } + + private void importCACertToOCSP() throws IOException { + IConfigStore config = CMS.getConfigStore(); + + // get certificate chain from CA + try { + String b64 = config.getString("preop.ca.pkcs7", ""); + + if (b64.equals("")) + throw new IOException("Failed to get certificate chain."); + + try { + // this could be a chain + X509Certificate[] certs = Cert.mapCertFromPKCS7(b64); + X509Certificate leafCert = null; + if (certs != null && certs.length > 0) { + if (certs[0].getSubjectDN().getName().equals(certs[0].getIssuerDN().getName())) { + leafCert = certs[certs.length - 1]; + } else { + leafCert = certs[0]; + } + + IOCSPAuthority ocsp = + (IOCSPAuthority) CMS.getSubsystem(IOCSPAuthority.ID); + IDefStore defStore = ocsp.getDefaultStore(); + + // (1) need to normalize (sort) the chain + + // (2) store certificate (and certificate chain) into + // database + ICRLIssuingPointRecord rec = defStore.createCRLIssuingPointRecord( + leafCert.getSubjectDN().getName(), + BIG_ZERO, + MINUS_ONE, null, null); + + try { + rec.set(ICRLIssuingPointRecord.ATTR_CA_CERT, leafCert.getEncoded()); + } catch (Exception e) { + // error + } + defStore.addCRLIssuingPoint(leafCert.getSubjectDN().getName(), rec); + //log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CA certificate " + leafCert.getSubjectDN().getName()); + + CMS.debug("DonePanel importCACertToOCSP: Added CA certificate."); + } + } catch (Exception e) { + throw new IOException("Failed to encode the certificate chain"); + } + } catch (IOException e) { + throw e; + } catch (Exception e) { + CMS.debug("DonePanel importCACertToOCSP: Failed to import the certificate chain into the OCSP"); + throw new IOException("Failed to import the certificate chain into the OCSP"); + } + } + + private String getCASubsystemCert() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + String host = ""; + int port = -1; + try { + host = cs.getString("preop.ca.hostname", ""); + port = cs.getInteger("preop.ca.httpsadminport", -1); + } catch (Exception e) { + } + + return getSubsystemCert(host, port, true); + } + + private String getCAUserId() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + String host = ""; + int port = -1; + try { + host = cs.getString("preop.ca.hostname", ""); + port = cs.getInteger("preop.ca.httpsport", -1); + } catch (Exception e) { + } + + return "CA-" + host + "-" + port; + } + + private void updateConnectorInfo(String ownagenthost, String ownagentsport) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + int port = -1; + String url = ""; + String host = null; + String transportCert = ""; + try { + url = cs.getString("preop.ca.url", ""); + if (!url.equals("")) { + host = cs.getString("preop.ca.hostname", ""); + port = cs.getInteger("preop.ca.httpsadminport", -1); + transportCert = cs.getString("kra.transport.cert", ""); + } + } catch (Exception e) { + } + + if (host == null) { + CMS.debug("DonePanel: preop.ca.url is not defined. External CA selected. No transport certificate setup is required"); + } else { + CMS.debug("DonePanel: Transport certificate is being setup in " + url); + String session_id = CMS.getConfigSDSessionId(); + String content = + "ca.connector.KRA.enable=true&ca.connector.KRA.local=false&ca.connector.KRA.timeout=30&ca.connector.KRA.uri=/kra/agent/kra/connector&ca.connector.KRA.host=" + + ownagenthost + + "&ca.connector.KRA.port=" + + ownagentsport + + "&ca.connector.KRA.transportCert=" + + URLEncoder.encode(transportCert, "UTF-8") + + "&sessionID=" + + session_id; + + updateConnectorInfo(host, port, true, content); + } + } + + private String getSubsystemNodeName(String type) { + if (type.equals("CA")) { + return "CAList"; + } else if (type.equals("KRA")) { + return "KRAList"; + } else if (type.equals("TKS")) { + return "TKSList"; + } else if (type.equals("OCSP")) { + return "OCSPList"; + } + + return ""; + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) {/* This should never be called */ + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java b/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java new file mode 100644 index 000000000..094aa7166 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java @@ -0,0 +1,136 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class DownloadPKCS12 extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -7770226137155537526L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + + public DownloadPKCS12() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("DownloadPKCS12: initializing..."); + super.init(sc); + CMS.debug("DownloadPKCS12: done initializing..."); + } + + /** + * Process the HTTP request. + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("DownloadPKCS12: processing..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + IConfigStore cs = CMS.getConfigStore(); + mRenderResult = false; + + // check the pin from the session + String pin = (String) httpReq.getSession().getAttribute("pin"); + if (pin == null) { + CMS.debug("DownloadPKCS12 process: Failed to get the pin from the cookie."); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + String cspin = ""; + try { + cspin = cs.getString("preop.pin"); + } catch (Exception e) { + } + + if (!pin.equals(cspin)) { + CMS.debug("DownloadPKCS12 process: Wrong pin"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + byte[] pkcs12 = null; + try { + String str = cs.getString("preop.pkcs12"); + pkcs12 = CryptoUtil.string2byte(str); + } catch (Exception e) { + } + + try { + httpResp.setContentType("application/x-pkcs12"); + httpResp.getOutputStream().write(pkcs12); + return; + } catch (Exception e) { + CMS.debug("DownloadPKCS12 process: Exception=" + e.toString()); + } + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetCertChain.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetCertChain.java new file mode 100644 index 000000000..02fbd7643 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetCertChain.java @@ -0,0 +1,158 @@ +// --- 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.csadmin; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.CertificateChain; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.xml.XMLObject; + +public class GetCertChain extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -356806997334418285L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + public GetCertChain() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param op 'downloadBIN' - return the binary certificate chain + * <li>http.param op 'displayIND' - display pretty-print of certificate chain components + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + CertificateChain certChain = ((ICertAuthority) mAuthority).getCACertChain(); + + if (certChain == null) { + CMS.debug( + "GetCertChain displayChain: cannot get the certificate chain."); + outputError(httpResp, "Error: Failed to get certificate chain."); + return; + } + + byte[] bytes = null; + + try { + ByteArrayOutputStream encoded = new ByteArrayOutputStream(); + + certChain.encode(encoded); + bytes = encoded.toByteArray(); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_ENCODING_CA_CHAIN_1", + e.toString())); + outputError(httpResp, + "Error: Failed to encode the certificate chain"); + } + + String chainBase64 = CMS.BtoA(bytes); + + chainBase64 = normalizeCertStr(chainBase64); + + try { + XMLObject xmlObj = null; + + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + xmlObj.addItemToContainer(root, "ChainBase64", chainBase64); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } + + private String normalizeCertStr(String s) { + StringBuffer val = new StringBuffer(); + + for (int i = 0; i < s.length(); i++) { + if (s.charAt(i) == '\n') { + continue; + } else if (s.charAt(i) == '\r') { + continue; + } else if (s.charAt(i) == '"') { + continue; + } else if (s.charAt(i) == ' ') { + continue; + } + val.append(s.charAt(i)); + } + return val.toString(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java new file mode 100644 index 000000000..33d82e9b8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java @@ -0,0 +1,228 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.net.InetAddress; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +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.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.password.IPasswordStore; +import com.netscape.cmsutil.xml.XMLObject; + +public class GetConfigEntries extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -7418561215631752315L; + private final static String SUCCESS = "0"; + private final static String AUTH_FAILURE = "2"; + + public GetConfigEntries() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + CMS.debug("GetConfigEntries init"); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param op 'downloadBIN' - return the binary certificate chain + * <li>http.param op 'displayIND' - display pretty-print of certificate chain components + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = null; + + try { + authToken = authenticate(cmsReq); + } catch (Exception e) { + CMS.debug("GetConfigEntries authentication failed"); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + // Get the operation code + String op = null; + + op = args.getValueAsString("op", null); + CMS.debug("GetConfigEntries process: op=" + op); + + XMLObject xmlObj = null; + try { + xmlObj = new XMLObject(); + } catch (Exception e) { + CMS.debug("GetConfigEntries process: Exception: " + e.toString()); + throw new EBaseException(e.toString()); + } + + Node root = xmlObj.createRoot("XMLResponse"); + 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())); + outputError(httpResp, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + "Error: Encountered problem during authorization."); + return; + } + + if (authzToken == null) { + outputError(httpResp, "Error: Not authorized"); + return; + } + + if (op != null) { + IConfigStore config = CMS.getConfigStore(); + String substores = args.getValueAsString("substores", ""); + StringTokenizer t = new StringTokenizer(substores, ","); + while (t.hasMoreTokens()) { + String name1 = t.nextToken(); + IConfigStore cs = config.getSubStore(name1); + Enumeration<String> enum1 = cs.getPropertyNames(); + + while (enum1.hasMoreElements()) { + String name = name1 + "." + enum1.nextElement(); + try { + String value = config.getString(name); + if (value.equals("localhost")) { + value = config.getString("machineName", InetAddress.getLocalHost().getHostName()); + } + Node container = xmlObj.createContainer(root, "Config"); + xmlObj.addItemToContainer(container, "name", name); + xmlObj.addItemToContainer(container, "value", value); + } catch (Exception ee) { + continue; + } + } + } + + String names = args.getValueAsString("names", ""); + StringTokenizer t1 = new StringTokenizer(names, ","); + while (t1.hasMoreTokens()) { + String name = t1.nextToken(); + String value = ""; + + try { + CMS.debug("Retrieving config name=" + name); + value = config.getString(name); + CMS.debug("Retrieving config value=" + value); + if (value.equals("localhost")) + value = config.getString("machineName", InetAddress.getLocalHost().getHostName()); + } catch (Exception ee) { + if (name.equals("internaldb.ldapauth.password")) { + value = getLDAPPassword(); + } else if (name.equals("internaldb.replication.password")) { + value = getReplicationPassword(); + } else + continue; + } + + Node container = xmlObj.createContainer(root, "Config"); + xmlObj.addItemToContainer(container, "name", name); + xmlObj.addItemToContainer(container, "value", value); + } + } + + try { + xmlObj.addItemToContainer(root, "Status", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + 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, ie, it will not return the default javascript. + } + + private String getLDAPPassword() { + IPasswordStore pwdStore = CMS.getPasswordStore(); + return pwdStore.getPassword("internaldb"); + } + + private String getReplicationPassword() { + IPasswordStore pwdStore = CMS.getPasswordStore(); + return pwdStore.getPassword("replicationdb"); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetCookie.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetCookie.java new file mode 100644 index 000000000..e6810ff42 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetCookie.java @@ -0,0 +1,315 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.URL; +import java.net.URLDecoder; +import java.util.Locale; +import java.util.Random; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISecurityDomainSessionTable; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +public class GetCookie extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 2466968231929541707L; + private static Random mRandom = null; + private final static int SESSION_MAX_AGE = 3600; + private String mErrorFormPath = null; + private String mFormPath = null; + + private final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE = + "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1"; + private final static String LOGGING_SIGNED_AUDIT_ROLE_ASSUME = + "LOGGING_SIGNED_AUDIT_ROLE_ASSUME_3"; + + public GetCookie() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + + CMS.debug("GetCookie init"); + mTemplates.remove(CMSRequest.SUCCESS); + mRandom = new Random(); + mErrorFormPath = sc.getInitParameter("errorTemplatePath"); + if (mOutputTemplatePath != null) { + mFormPath = mOutputTemplatePath; + } + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + CMS.debug("GetCookie start"); + IAuthToken authToken = null; + IConfigStore cs = CMS.getConfigStore(); + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + String url = httpReq.getParameter("url"); + CMS.debug("GetCookie before auth, url =" + url); + String url_e = ""; + URL u = null; + try { + url_e = URLDecoder.decode(url, "UTF-8"); + u = new URL(url_e); + } catch (Exception eee) { + throw new ECMSGWException( + "GetCookie missing parameter: url"); + } + + int index2 = url_e.indexOf("subsystem="); + String subsystem = ""; + if (index2 > 0) { + subsystem = url.substring(index2 + 10); + int index1 = subsystem.indexOf("&"); + if (index1 > 0) + subsystem = subsystem.substring(0, index1); + } + + try { + authToken = authenticate(cmsReq); + } catch (Exception e) { + CMS.debug("GetCookie authentication failed"); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + header.addStringValue("sd_uid", ""); + header.addStringValue("sd_pwd", ""); + header.addStringValue("host", u.getHost()); + header.addStringValue("sdhost", CMS.getEESSLHost()); + header.addStringValue("subsystem", subsystem); + header.addStringValue("url", url_e); + header.addStringValue("errorString", "Failed Authentication"); + String sdname = cs.getString("securitydomain.name", ""); + header.addStringValue("sdname", sdname); + + CMS.debug("mErrorFormPath=" + mErrorFormPath); + try { + form = getTemplate(mErrorFormPath, httpReq, locale); + } catch (IOException eee) { + CMS.debug("GetCookie process: cant locate the form"); + /* + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + */ + } + + if (form == null) { + CMS.debug("GetCookie::process() - form is null!"); + throw new EBaseException("form is null"); + } + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + cmsReq.setStatus(CMSRequest.SUCCESS); + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException ee) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", ee.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + return; + } + + String cookie = ""; + String auditMessage = ""; + + if (authToken != null) { + String uid = authToken.getInString("uid"); + String groupname = getGroupName(uid, subsystem); + + if (groupname != null) { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + uid, + ILogger.SUCCESS, + groupname); + audit(auditMessage); + + // assign cookie + long num = mRandom.nextLong(); + cookie = num + ""; + ISecurityDomainSessionTable ctable = CMS.getSecurityDomainSessionTable(); + String addr = ""; + try { + addr = u.getHost(); + } catch (Exception e) { + } + String ip = ""; + try { + ip = InetAddress.getByName(addr).toString(); + int index = ip.indexOf("/"); + if (index > 0) + ip = ip.substring(index + 1); + } catch (Exception e) { + } + + String auditParams = "operation;;issue_token+token;;" + cookie + "+ip;;" + ip + + "+uid;;" + uid + "+groupname;;" + groupname; + + int status = ctable.addEntry(cookie, ip, uid, groupname); + if (status == ISecurityDomainSessionTable.SUCCESS) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE, + uid, + ILogger.SUCCESS, + auditParams); + audit(auditMessage); + } else { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE, + uid, + ILogger.FAILURE, + auditParams); + audit(auditMessage); + } + + try { + if (!url.startsWith("$")) { + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + CMS.debug("GetCookie process: cant locate the form"); + /* + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + */ + } + + header.addStringValue("url", url); + header.addStringValue("session_id", cookie); + + try { + ServletOutputStream out = httpResp.getOutputStream(); + + cmsReq.setStatus(CMSRequest.SUCCESS); + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + } catch (Exception e) { + } + } else { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ROLE_ASSUME, + uid, + ILogger.FAILURE, + "Enterprise " + subsystem + " Administrators"); + audit(auditMessage); + } + } + } + + private String getGroupName(String uid, String subsystemname) { + IUGSubsystem subsystem = + (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID)); + if (subsystem.isMemberOf(uid, "Enterprise CA Administrators") && + subsystemname.equals("CA")) { + return "Enterprise CA Administrators"; + } else if (subsystem.isMemberOf(uid, "Enterprise KRA Administrators") && + subsystemname.equals("KRA")) { + return "Enterprise KRA Administrators"; + } else if (subsystem.isMemberOf(uid, "Enterprise OCSP Administrators") && + subsystemname.equals("OCSP")) { + return "Enterprise OCSP Administrators"; + } else if (subsystem.isMemberOf(uid, "Enterprise TKS Administrators") && + subsystemname.equals("TKS")) { + return "Enterprise TKS Administrators"; + } else if (subsystem.isMemberOf(uid, "Enterprise RA Administrators") && + subsystemname.equals("RA")) { + return "Enterprise RA Administrators"; + } else if (subsystem.isMemberOf(uid, "Enterprise TPS Administrators") && + subsystemname.equals("TPS")) { + return "Enterprise TPS Administrators"; + } + + return null; + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java new file mode 100644 index 000000000..999f13815 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java @@ -0,0 +1,239 @@ +// --- 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.csadmin; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPSearchConstraints; +import netscape.ldap.LDAPSearchResults; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.ldap.ILdapConnFactory; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.xml.XMLObject; + +public class GetDomainXML extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 3079546345000720649L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + public GetDomainXML() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("GetDomainXML: initializing..."); + super.init(sc); + CMS.debug("GetDomainXML: done initializing..."); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param op 'downloadBIN' - return the binary certificate chain + * <li>http.param op 'displayIND' - display pretty-print of certificate chain components + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("GetDomainXML: processing..."); + + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + String status = SUCCESS; + String basedn = null; + String secstore = null; + + IConfigStore cs = CMS.getConfigStore(); + try { + secstore = cs.getString("securitydomain.store"); + basedn = cs.getString("internaldb.basedn"); + } catch (Exception e) { + CMS.debug("Unable to determine the security domain name or internal basedn. Please run the domaininfo migration script"); + } + + try { + XMLObject response = new XMLObject(); + Node root = response.createRoot("XMLResponse"); + + if ((secstore != null) && (basedn != null) && (secstore.equals("ldap"))) { + ILdapConnFactory connFactory = null; + LDAPConnection conn = null; + try { + // get data from ldap + String filter = "objectclass=pkiSecurityGroup"; + LDAPSearchConstraints cons = null; + String[] attrs = null; + String dn = "ou=Security Domain," + basedn; + + IConfigStore ldapConfig = cs.getSubStore("internaldb"); + connFactory = CMS.getLdapBoundConnFactory(); + connFactory.init(ldapConfig); + conn = connFactory.getConn(); + + // get the security domain name + String secdomain = (String) conn.read(dn).getAttribute("name").getStringValues().nextElement(); + + XMLObject xmlObj = new XMLObject(); + Node domainInfo = xmlObj.createRoot("DomainInfo"); + xmlObj.addItemToContainer(domainInfo, "Name", secdomain); + + // this should return CAList, KRAList etc. + LDAPSearchResults res = conn.search(dn, LDAPConnection.SCOPE_ONE, filter, + attrs, true, cons); + + while (res.hasMoreElements()) { + int count = 0; + dn = res.next().getDN(); + String listName = dn.substring(3, dn.indexOf(",")); + String subType = listName.substring(0, listName.indexOf("List")); + Node listNode = xmlObj.createContainer(domainInfo, listName); + + filter = "objectclass=pkiSubsystem"; + LDAPSearchResults res2 = conn.search(dn, LDAPConnection.SCOPE_ONE, filter, + attrs, false, cons); + while (res2.hasMoreElements()) { + Node node = xmlObj.createContainer(listNode, subType); + LDAPEntry entry = res2.next(); + LDAPAttributeSet entryAttrs = entry.getAttributeSet(); + @SuppressWarnings("unchecked") + Enumeration<LDAPAttribute> attrsInSet = entryAttrs.getAttributes(); + while (attrsInSet.hasMoreElements()) { + LDAPAttribute nextAttr = attrsInSet.nextElement(); + String attrName = nextAttr.getName(); + if ((!attrName.equals("cn")) && (!attrName.equals("objectClass"))) { + String attrValue = (String) nextAttr.getStringValues().nextElement(); + xmlObj.addItemToContainer(node, securityDomainLDAPtoXML(attrName), attrValue); + } + } + count++; + } + xmlObj.addItemToContainer(listNode, "SubsystemCount", Integer.toString(count)); + } + + // Add new xml object as string to response. + response.addItemToContainer(root, "DomainInfo", xmlObj.toXMLString()); + } catch (Exception e) { + CMS.debug("GetDomainXML: Failed to read domain.xml from ldap " + e.toString()); + status = FAILED; + } finally { + if ((conn != null) && (connFactory != null)) { + CMS.debug("Releasing ldap connection"); + connFactory.returnConn(conn); + } + } + } else { + // get data from file store + + String path = CMS.getConfigStore().getString("instanceRoot", "") + + "/conf/domain.xml"; + + CMS.debug("GetDomainXML: got path=" + path); + + try { + CMS.debug("GetDomainXML: Reading domain.xml from file ..."); + FileInputStream fis = new FileInputStream(path); + int s = fis.available(); + + CMS.debug("GetDomainXML: size " + s); + byte buf[] = new byte[s]; + + fis.read(buf, 0, s); + fis.close(); + CMS.debug("GetDomainXML: Done Reading domain.xml..."); + + response.addItemToContainer(root, "DomainInfo", new String(buf)); + } catch (Exception e) { + CMS.debug("Failed to read domain.xml from file" + e.toString()); + status = FAILED; + } + } + + response.addItemToContainer(root, "Status", status); + byte[] cb = response.toByteArray(); + outputResult(httpResp, "application/xml", cb); + + } catch (Exception e) { + CMS.debug("GetDomainXML: Failed to send the XML output" + e.toString()); + } + } + + protected String securityDomainLDAPtoXML(String attribute) { + if (attribute.equals("host")) + return "Host"; + else + return attribute; + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetStatus.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetStatus.java new file mode 100644 index 000000000..4dc6f0ff6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetStatus.java @@ -0,0 +1,109 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.xml.XMLObject; + +public class GetStatus extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -2852842030221659847L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + public GetStatus() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + IConfigStore config = CMS.getConfigStore(); + + String state = config.getString("cs.state", ""); + String type = config.getString("cs.type", ""); + + try { + XMLObject xmlObj = null; + + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "State", state); + xmlObj.addItemToContainer(root, "Type", type); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java new file mode 100644 index 000000000..288cfad60 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java @@ -0,0 +1,129 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.X509Certificate; +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.xml.XMLObject; + +public class GetSubsystemCert extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -5720342238234153488L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + public GetSubsystemCert() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + } + + /** + * Process the HTTP request. + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IConfigStore cs = CMS.getConfigStore(); + String nickname = ""; + try { + nickname = cs.getString("ca.subsystem.nickname", ""); + String tokenname = cs.getString("ca.subsystem.tokenname", ""); + if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) + nickname = tokenname + ":" + nickname; + } catch (Exception e) { + } + + CMS.debug("GetSubsystemCert process: nickname=" + nickname); + String s = ""; + try { + CryptoManager cm = CryptoManager.getInstance(); + X509Certificate cert = cm.findCertByNickname(nickname); + + if (cert == null) { + CMS.debug("GetSubsystemCert process: subsystem cert is null"); + outputError(httpResp, "Error: Failed to get subsystem certificate."); + return; + } + + byte[] bytes = cert.getEncoded(); + s = CryptoUtil.normalizeCertStr(CryptoUtil.base64Encode(bytes)); + } catch (Exception e) { + CMS.debug("GetSubsystemCert process: exception: " + e.toString()); + } + + try { + XMLObject xmlObj = null; + xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + xmlObj.addItemToContainer(root, "Status", SUCCESS); + xmlObj.addItemToContainer(root, "Cert", s); + byte[] cb = xmlObj.toByteArray(); + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java new file mode 100644 index 000000000..f97d3e5e1 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java @@ -0,0 +1,151 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.xml.XMLObject; + +public class GetTokenInfo extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -8416582986909026263L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + public GetTokenInfo() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + CMS.debug("GetTokenInfo init"); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param op 'downloadBIN' - return the binary certificate chain + * <li>http.param op 'displayIND' - display pretty-print of certificate chain components + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + XMLObject xmlObj = null; + try { + xmlObj = new XMLObject(); + } catch (Exception e) { + CMS.debug("GetTokenInfo process: Exception: " + e.toString()); + throw new EBaseException(e.toString()); + } + + Node root = xmlObj.createRoot("XMLResponse"); + + IConfigStore config = CMS.getConfigStore(); + + String certlist = ""; + try { + certlist = config.getString("cloning.list"); + } catch (Exception e) { + } + + StringTokenizer t1 = new StringTokenizer(certlist, ","); + while (t1.hasMoreTokens()) { + String name = t1.nextToken(); + if (name.equals("sslserver")) + continue; + name = "cloning." + name + ".nickname"; + String value = ""; + + try { + value = config.getString(name); + } catch (Exception ee) { + continue; + } + + Node container = xmlObj.createContainer(root, "Config"); + xmlObj.addItemToContainer(container, "name", name); + xmlObj.addItemToContainer(container, "value", value); + } + + String value = ""; + String name = "cloning.module.token"; + try { + value = config.getString(name); + } catch (Exception e) { + } + + Node container = xmlObj.createContainer(root, "Config"); + xmlObj.addItemToContainer(container, "name", name); + xmlObj.addItemToContainer(container, "value", value); + + try { + xmlObj.addItemToContainer(root, "Status", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + 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, ie, it will not return the default javascript. + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java b/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java new file mode 100644 index 000000000..87a1788d6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java @@ -0,0 +1,180 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.security.cert.CertificateEncodingException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +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.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.security.ITransportKeyUnit; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.xml.XMLObject; + +/** + * This servlet retrieves the transport certificate from DRM. + */ +public class GetTransportCert extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 2495152202191979339L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + + public GetTransportCert() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("GetTransportCert: initializing..."); + super.init(sc); + CMS.debug("GetTransportCert: done initializing..."); + } + + /** + * Process the HTTP request. + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("UpdateUpdater: processing..."); + + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = null; + try { + authToken = authenticate(cmsReq); + CMS.debug("GetTransportCert authentication successful."); + } catch (Exception e) { + CMS.debug("GetTransportCert: authentication failed."); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + if (authToken == null) { + CMS.debug("GetTransportCert: authentication failed."); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + AuthzToken authzToken = null; + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, + "read"); + CMS.debug("GetTransportCert authorization successful."); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + "Error: Encountered problem during authorization."); + return; + } + + if (authzToken == null) { + outputError(httpResp, "Error: Not authorized"); + return; + } + + IKeyRecoveryAuthority kra = + (IKeyRecoveryAuthority) mAuthority; + ITransportKeyUnit tu = kra.getTransportKeyUnit(); + org.mozilla.jss.crypto.X509Certificate transportCert = + tu.getCertificate(); + + String mime64 = ""; + try { + mime64 = CMS.BtoA(transportCert.getEncoded()); + mime64 = com.netscape.cmsutil.util.Cert.normalizeCertStrAndReq(mime64); + } catch (CertificateEncodingException eee) { + CMS.debug("GetTransportCert: Failed to encode certificate"); + } + + // send success status back to the requestor + try { + CMS.debug("GetTransportCert: Sending response " + mime64); + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + xmlObj.addItemToContainer(root, "TransportCert", mime64); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("GetTransportCert: Failed to send the XML output " + e); + } + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java new file mode 100644 index 000000000..9044dec04 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java @@ -0,0 +1,194 @@ +// --- 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.csadmin; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class HierarchyPanel extends WizardPanelBase { + + public HierarchyPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("PKI Hierarchy"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("PKI Hierarchy"); + setId(id); + } + + public boolean shouldSkip() { + + // we dont need to ask the hierachy if we are + // setting up a clone + try { + IConfigStore c = CMS.getConfigStore(); + String s = c.getString("preop.subsystem.select", + null); + if (s != null && s.equals("clone")) { + // mark this panel as done + c.putString("preop.hierarchy.select", "root"); + c.putString("hierarchy.select", "Clone"); + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.hierarchy.select", ""); + cs.putString("hierarchy.select", ""); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.hierarchy.select", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "PKI Hierarchy"); + IConfigStore config = CMS.getConfigStore(); + + if (isPanelDone()) { + try { + String s = config.getString("preop.hierarchy.select"); + + if (s.equals("root")) { + context.put("check_root", "checked"); + } else if (s.equals("join")) { + context.put("check_join", "checked"); + } + } catch (Exception e) { + CMS.debug(e.toString()); + } + } else { + context.put("check_root", "checked"); + context.put("check_join", ""); + } + + context.put("panel", "admin/console/config/hierarchypanel.vm"); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + try { + String cstype = config.getString("preop.subsystem.select", ""); + if (cstype.equals("clone")) { + context.put("updateStatus", "success"); + return; + } + } catch (Exception e) { + } + + String select = HttpInput.getID(request, "choice"); + + if (select == null) { + CMS.debug("HierarchyPanel: choice not found"); + context.put("updateStatus", "failure"); + throw new IOException("choice not found"); + } + + if (select.equals("root")) { + config.putString("preop.hierarchy.select", "root"); + config.putString("hierarchy.select", "Root"); + config.putString("preop.ca.type", "sdca"); + try { + config.commit(false); + } catch (EBaseException e) { + } + } else if (select.equals("join")) { + config.putString(PCERT_PREFIX + "signing.type", "remote"); + config.putString("preop.hierarchy.select", "join"); + config.putString("hierarchy.select", "Subordinate"); + } else { + config.putString(PCERT_PREFIX + "signing.type", "remote"); + CMS.debug("HierarchyPanel: invalid choice " + select); + context.put("updateStatus", "failure"); + throw new IOException("invalid choice " + select); + } + context.put("updateStatus", "success"); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java new file mode 100644 index 000000000..93c26cdf3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java @@ -0,0 +1,341 @@ +// --- 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.csadmin; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPException; +import netscape.security.x509.X509CertImpl; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class ImportAdminCertPanel extends WizardPanelBase { + + public ImportAdminCertPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Import Administrator's Certificate"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Import Administrator's Certificate"); + setId(id); + } + + public boolean isSubPanel() { + return true; + } + + public void cleanUp() throws IOException { + } + + public boolean isPanelDone() { + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("ImportAdminCertPanel: display"); + context.put("errorString", ""); + context.put("title", "Import Administrator's Certificate"); + context.put("panel", "admin/console/config/importadmincertpanel.vm"); + context.put("import", "true"); + + IConfigStore cs = CMS.getConfigStore(); + + String type = ""; + + try { + type = cs.getString("preop.ca.type", ""); + } catch (Exception e) { + } + + try { + String serialno = cs.getString("preop.admincert.serialno.0"); + + context.put("serialNumber", serialno); + } catch (Exception e) { + context.put("errorString", "Failed to get serial number."); + } + + context.put("caType", type); + + ISubsystem ca = (ISubsystem) CMS.getSubsystem("ca"); + + if (ca == null) { + context.put("ca", "false"); + } else { + context.put("ca", "true"); + } + + String caHost = ""; + String caPort = ""; + String info = ""; + + if (ca == null) { + if (type.equals("otherca")) { + try { + // this is a non-CA system that has elected to have its certificates + // signed by a CA outside of the security domain. + // in this case, we submitted the cert request for the admin cert to + // to security domain host. + caHost = cs.getString("securitydomain.host", ""); + caPort = cs.getString("securitydomain.httpsadminport", ""); + } catch (Exception e) { + } + } else if (type.equals("sdca")) { + try { + // this is a non-CA system that submitted its certs to a CA + // within the security domain. In this case, we submitted the cert + // request for the admin cert to this CA + caHost = cs.getString("preop.ca.hostname", ""); + caPort = cs.getString("preop.ca.httpsadminport", ""); + } catch (Exception e) { + } + } + } else { + // for CAs, we always generate our own admin certs + // send our own connection details + try { + caHost = cs.getString("service.machineName", ""); + caPort = cs.getString("pkicreate.admin_secure_port", ""); + } catch (Exception e) { + } + } + + String pkcs7 = ""; + try { + pkcs7 = cs.getString("preop.admincert.pkcs7", ""); + } catch (Exception e) { + } + + context.put("pkcs7", pkcs7); + context.put("caHost", caHost); + context.put("caPort", caPort); + context.put("info", info); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore cs = CMS.getConfigStore(); + + String type = ""; + String subsystemtype = ""; + String selected_hierarchy = ""; + + try { + type = cs.getString("preop.ca.type", ""); + subsystemtype = cs.getString("cs.type", ""); + selected_hierarchy = cs.getString("preop.hierarchy.select", ""); + } catch (Exception e) { + } + + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem( + ICertificateAuthority.ID); + + if (ca == null) { + context.put("ca", "false"); + } else { + context.put("ca", "true"); + } + context.put("caType", type); + + X509CertImpl certs[] = new X509CertImpl[1]; + + // REMINDER: This panel is NOT used by "clones" + if (ca != null) { + String serialno = null; + + if (selected_hierarchy.equals("root")) { + CMS.debug("ImportAdminCertPanel update: " + + "Root CA subsystem - " + + "(new Security Domain)"); + } else { + CMS.debug("ImportAdminCertPanel update: " + + "Subordinate CA subsystem - " + + "(new Security Domain)"); + } + + try { + serialno = cs.getString("preop.admincert.serialno.0"); + } catch (Exception e) { + CMS.debug( + "ImportAdminCertPanel update: Failed to get request id."); + context.put("updateStatus", "failure"); + throw new IOException("Failed to get request id."); + } + + ICertificateRepository repost = ca.getCertificateRepository(); + + try { + certs[0] = repost.getX509Certificate( + new BigInteger(serialno, 16)); + } catch (Exception ee) { + } + } else { + String dir = null; + + // REMINDER: This panel is NOT used by "clones" + if (subsystemtype.equals("CA")) { + if (selected_hierarchy.equals("root")) { + CMS.debug("ImportAdminCertPanel update: " + + "Root CA subsystem - " + + "(existing Security Domain)"); + } else { + CMS.debug("ImportAdminCertPanel update: " + + "Subordinate CA subsystem - " + + "(existing Security Domain)"); + } + } else { + CMS.debug("ImportAdminCertPanel update: " + + subsystemtype + + " subsystem"); + } + + try { + dir = cs.getString("preop.admincert.b64", ""); + CMS.debug("ImportAdminCertPanel update: dir=" + dir); + } catch (Exception ee) { + } + + try { + BufferedReader reader = new BufferedReader( + new FileReader(dir)); + String b64 = ""; + + StringBuffer sb = new StringBuffer(); + while (reader.ready()) { + sb.append(reader.readLine()); + } + b64 = sb.toString(); + reader.close(); + + b64 = b64.trim(); + b64 = CryptoUtil.stripCertBrackets(b64); + CMS.debug("ImportAdminCertPanel update: b64=" + b64); + byte[] b = CryptoUtil.base64Decode(b64); + certs[0] = new X509CertImpl(b); + } catch (Exception e) { + CMS.debug("ImportAdminCertPanel update: " + e.toString()); + } + } + + try { + IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(IUGSubsystem.ID); + String uid = cs.getString("preop.admin.uid"); + IUser user = ug.getUser(uid); + user.setX509Certificates(certs); + ug.addUserCert(user); + } catch (LDAPException e) { + CMS.debug("ImportAdminCertPanel update: failed to add certificate to the internal database. Exception: " + + e.toString()); + if (e.getLDAPResultCode() != LDAPException.ATTRIBUTE_OR_VALUE_EXISTS) { + context.put("updateStatus", "failure"); + throw new IOException(e.toString()); + } + } catch (Exception e) { + CMS.debug( + "ImportAdminCertPanel update: failed to add certificate. Exception: " + + e.toString()); + context.put("updateStatus", "failure"); + throw new IOException(e.toString()); + } + + context.put("errorString", ""); + context.put("info", ""); + context.put("title", "Import Administrator Certificate"); + context.put("panel", "admin/console/config/importadmincertpanel.vm"); + context.put("updateStatus", "success"); + } + + public boolean shouldSkip() { + try { + IConfigStore c = CMS.getConfigStore(); + String s = c.getString("preop.subsystem.select", null); + if (s != null && s.equals("clone")) { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + /* This should never be called */ + context.put("title", "Import Administrator Certificate"); + context.put("panel", "admin/console/config/importadmincertpanel.vm"); + context.put("info", ""); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ImportCAChainPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/ImportCAChainPanel.java new file mode 100755 index 000000000..d0ccb58e9 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ImportCAChainPanel.java @@ -0,0 +1,145 @@ +// --- 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.csadmin; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class ImportCAChainPanel extends WizardPanelBase { + + public ImportCAChainPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Import CA's Certificate Chain"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Import CA's Certificate Chain"); + setId(id); + } + + public boolean isSubPanel() { + return false; + } + + public void cleanUp() throws IOException { + } + + public boolean isPanelDone() { + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("ImportCACertChain: display"); + context.put("errorString", ""); + context.put("title", "Import CA's Certificate Chain"); + context.put("panel", "admin/console/config/importcachainpanel.vm"); + context.put("import", "true"); + + IConfigStore cs = CMS.getConfigStore(); + try { + context.put("machineName", cs.getString("machineName")); + context.put("https_port", cs.getString("pkicreate.ee_secure_port")); + context.put("http_port", cs.getString("pkicreate.unsecure_port")); + } catch (EBaseException e) { + CMS.debug("ImportCACertChain:display: Exception: " + e.toString()); + context.put("errorString", "Error loading values for Import CA Certificate Panel"); + } + + ISubsystem ca = (ISubsystem) CMS.getSubsystem("ca"); + + if (ca == null) { + context.put("ca", "false"); + } else { + context.put("ca", "true"); + } + + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + + context.put("errorString", ""); + context.put("title", "Import CA's Certificate Chain"); + context.put("panel", "admin/console/config/importcachainpanel.vm"); + context.put("updateStatus", "success"); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + /* This should never be called */ + IConfigStore cs = CMS.getConfigStore(); + try { + context.put("machineName", cs.getString("machineName")); + context.put("https_port", cs.getString("pkicreate.ee_secure_port")); + context.put("http_port", cs.getString("pkicreate.unsecure_port")); + context.put("title", "Import CA's Certificate Chain"); + context.put("panel", "admin/console/config/importcachainpanel.vm"); + } catch (EBaseException e) { + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java b/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java new file mode 100644 index 000000000..66ca8a8bf --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java @@ -0,0 +1,179 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mozilla.jss.CryptoManager; +import org.w3c.dom.Node; + +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.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.xml.XMLObject; + +/** + * This servlet imports DRM's transport certificate into TKS. + */ +public class ImportTransportCert extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 7490067757951541235L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + + public ImportTransportCert() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("ImportTransportCert: initializing..."); + super.init(sc); + CMS.debug("ImportTransportCert: done initializing..."); + } + + /** + * Process the HTTP request. + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("UpdateUpdater: processing..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = null; + try { + authToken = authenticate(cmsReq); + CMS.debug("ImportTransportCert authentication successful."); + } catch (Exception e) { + CMS.debug("ImportTransportCert: authentication failed."); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + if (authToken == null) { + CMS.debug("ImportTransportCert: authentication failed."); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + AuthzToken authzToken = null; + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, + "modify"); + CMS.debug("ImportTransportCert authorization successful."); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + "Error: Encountered problem during authorization."); + return; + } + + if (authzToken == null) { + outputError(httpResp, "Error: Not authorized"); + return; + } + + IConfigStore cs = CMS.getConfigStore(); + + String certsString = httpReq.getParameter("certificate"); + + try { + CryptoManager cm = CryptoManager.getInstance(); + CMS.debug("ImportTransportCert: Importing certificate"); + org.mozilla.jss.crypto.X509Certificate cert = + cm.importCACertPackage(CMS.AtoB(certsString)); + String nickName = cert.getNickname(); + CMS.debug("ImportTransportCert: nickname " + nickName); + cs.putString("tks.drm_transport_cert_nickname", nickName); + CMS.debug("ImportTransportCert: Commiting configuration"); + cs.commit(false); + + // send success status back to the requestor + CMS.debug("ImportTransportCert: Sending response"); + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("ImportTransportCert: Failed to send the XML output " + e); + } + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/LDAPSecurityDomainSessionTable.java b/base/common/src/com/netscape/cms/servlet/csadmin/LDAPSecurityDomainSessionTable.java new file mode 100644 index 000000000..b9932722e --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/LDAPSecurityDomainSessionTable.java @@ -0,0 +1,295 @@ +// --- 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) 2010 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.csadmin; + +import java.util.Date; +import java.util.Enumeration; +import java.util.Vector; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPSearchResults; +import netscape.ldap.LDAPv2; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISecurityDomainSessionTable; +import com.netscape.certsrv.ldap.ELdapException; +import com.netscape.certsrv.ldap.ILdapConnFactory; + +/** + * This object stores the values for IP, uid and group based on the cookie id in LDAP. + * Entries are stored under ou=Security Domain, ou=sessions, $basedn + */ +public class LDAPSecurityDomainSessionTable + implements ISecurityDomainSessionTable { + + private long m_timeToLive; + private ILdapConnFactory mLdapConnFactory = null; + + public LDAPSecurityDomainSessionTable(long timeToLive) throws ELdapException, EBaseException { + m_timeToLive = timeToLive; + IConfigStore cs = CMS.getConfigStore(); + IConfigStore internaldb = cs.getSubStore("internaldb"); + mLdapConnFactory = CMS.getLdapBoundConnFactory(); + mLdapConnFactory.init(internaldb); + } + + public int addEntry(String sessionId, String ip, + String uid, String group) { + IConfigStore cs = CMS.getConfigStore(); + LDAPConnection conn = null; + boolean sessions_exists = true; + int status = FAILURE; + + String basedn = null; + String sessionsdn = null; + try { + basedn = cs.getString("internaldb.basedn"); + sessionsdn = "ou=sessions,ou=Security Domain," + basedn; + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: addEntry: failed to read basedn" + e); + return status; + } + + try { + // create session entry (if it does not exist) + conn = mLdapConnFactory.getConn(); + + LDAPEntry entry = null; + LDAPAttributeSet attrs = null; + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "organizationalUnit")); + attrs.add(new LDAPAttribute("ou", "sessions")); + entry = new LDAPEntry(sessionsdn, attrs); + conn.add(entry); + } catch (Exception e) { + if ((e instanceof LDAPException) + && (((LDAPException) e).getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS)) { + // continue + } else { + CMS.debug("SecurityDomainSessionTable: unable to create ou=sessions:" + e); + sessions_exists = false; + } + } + + // add new entry + try { + LDAPEntry entry = null; + LDAPAttributeSet attrs = null; + String entrydn = "cn=" + sessionId + "," + sessionsdn; + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "securityDomainSessionEntry")); + attrs.add(new LDAPAttribute("cn", sessionId)); + attrs.add(new LDAPAttribute("host", ip)); + attrs.add(new LDAPAttribute("uid", uid)); + attrs.add(new LDAPAttribute("cmsUserGroup", group)); + attrs.add(new LDAPAttribute("dateOfCreate", Long.toString((new Date()).getTime()))); + + entry = new LDAPEntry(entrydn, attrs); + if (sessions_exists) { + conn.add(entry); + CMS.debug("SecurityDomainSessionTable: added session entry" + sessionId); + status = SUCCESS; + } + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: unable to create session entry" + sessionId + ": " + e); + } + + try { + mLdapConnFactory.returnConn(conn); + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable:addEntry: Error in disconnecting from database: " + e); + } + return status; + } + + public int removeEntry(String sessionId) { + IConfigStore cs = CMS.getConfigStore(); + LDAPConnection conn = null; + int status = FAILURE; + try { + String basedn = cs.getString("internaldb.basedn"); + String dn = "cn=" + sessionId + ",ou=sessions,ou=Security Domain," + basedn; + conn = mLdapConnFactory.getConn(); + conn.delete(dn); + status = SUCCESS; + } catch (Exception e) { + if ((e instanceof LDAPException) + && (((LDAPException) e).getLDAPResultCode() == LDAPException.NO_SUCH_OBJECT)) { + // continue + } else { + CMS.debug("SecurityDomainSessionTable: unable to delete session " + sessionId + ": " + e); + } + } + try { + mLdapConnFactory.returnConn(conn); + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: removeEntry: Error in disconnecting from database: " + e); + } + return status; + } + + public boolean isSessionIdExist(String sessionId) { + IConfigStore cs = CMS.getConfigStore(); + LDAPConnection conn = null; + boolean ret = false; + try { + String basedn = cs.getString("internaldb.basedn"); + String sessionsdn = "ou=sessions,ou=Security Domain," + basedn; + String filter = "(cn=" + sessionId + ")"; + String[] attrs = { "cn" }; + + conn = mLdapConnFactory.getConn(); + LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false); + if (res.getCount() > 0) + ret = true; + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: unable to query session " + sessionId + ": " + e); + } + + try { + mLdapConnFactory.returnConn(conn); + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: isSessionIdExist: Error in disconnecting from database: " + e); + } + return ret; + } + + public Enumeration<String> getSessionIds() { + IConfigStore cs = CMS.getConfigStore(); + LDAPConnection conn = null; + Vector<String> ret = new Vector<String>(); + + try { + String basedn = cs.getString("internaldb.basedn"); + String sessionsdn = "ou=sessions,ou=Security Domain," + basedn; + String filter = "(objectclass=securityDomainSessionEntry)"; + String[] attrs = { "cn" }; + + conn = mLdapConnFactory.getConn(); + LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false); + while (res.hasMoreElements()) { + LDAPEntry entry = res.next(); + ret.add(entry.getAttribute("cn").getStringValueArray()[0]); + } + } catch (LDAPException e) { + switch (e.getLDAPResultCode()) { + case LDAPException.NO_SUCH_OBJECT: + CMS.debug("SecurityDomainSessionTable: getSessionIds(): no sessions have been created"); + break; + default: + CMS.debug("SecurityDomainSessionTable: unable to query sessionIds due to ldap exception: " + e); + } + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: unable to query sessionIds: " + e); + } + + try { + mLdapConnFactory.returnConn(conn); + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: getSessionIds: Error in disconnecting from database: " + e); + } + + return ret.elements(); + } + + private String getStringValue(String sessionId, String attr) { + IConfigStore cs = CMS.getConfigStore(); + LDAPConnection conn = null; + String ret = null; + try { + String basedn = cs.getString("internaldb.basedn"); + String sessionsdn = "ou=sessions,ou=Security Domain," + basedn; + String filter = "(cn=" + sessionId + ")"; + String[] attrs = { attr }; + conn = mLdapConnFactory.getConn(); + LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false); + if (res.getCount() > 0) { + LDAPEntry entry = res.next(); + ret = entry.getAttribute(attr).getStringValueArray()[0]; + } + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: unable to query session " + sessionId + ": " + e); + } + + try { + mLdapConnFactory.returnConn(conn); + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: isSessionIdExist: Error in disconnecting from database: " + e); + } + return ret; + } + + public String getIP(String sessionId) { + return getStringValue(sessionId, "host"); + } + + public String getUID(String sessionId) { + return getStringValue(sessionId, "uid"); + } + + public String getGroup(String sessionId) { + return getStringValue(sessionId, "cmsUserGroup"); + } + + public long getBeginTime(String sessionId) { + String beginStr = getStringValue(sessionId, "dateOfCreate"); + if (beginStr != null) { + return Long.parseLong(beginStr); + } + return -1; + } + + public long getTimeToLive() { + return m_timeToLive; + } + + public int getSize() { + IConfigStore cs = CMS.getConfigStore(); + LDAPConnection conn = null; + int ret = 0; + + try { + String basedn = cs.getString("internaldb.basedn"); + String sessionsdn = "ou=sessions,ou=Security Domain," + basedn; + String filter = "(objectclass=securityDomainSessionEntry)"; + String[] attrs = { "cn" }; + + conn = mLdapConnFactory.getConn(); + LDAPSearchResults res = conn.search(sessionsdn, LDAPv2.SCOPE_SUB, filter, attrs, false); + ret = res.getCount(); + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: unable to query sessionIds: " + e); + } + + try { + mLdapConnFactory.returnConn(conn); + } catch (Exception e) { + CMS.debug("SecurityDomainSessionTable: getSessionIds: Error in disconnecting from database: " + e); + } + + return ret; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/LoginServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/LoginServlet.java new file mode 100644 index 000000000..713cb170a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/LoginServlet.java @@ -0,0 +1,72 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; + +public class LoginServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = -4766622132710080340L; + + public boolean authenticate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + return true; + } + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + Template template = null; + + try { + String pin = request.getParameter("pin"); + + if (pin == null) { + context.put("error", ""); + } else { + String cspin = CMS.getConfigStore().getString("preop.pin"); + + if (cspin != null && cspin.equals(pin)) { + // create session + request.getSession(true).setAttribute("pin", cspin); + // pin match, redirect to the welcome page + response.sendRedirect("wizard"); + return null; + } else { + context.put("error", "Login Failed"); + } + } + template = Velocity.getTemplate("admin/console/config/login.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java new file mode 100644 index 000000000..1d833ca9b --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java @@ -0,0 +1,158 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +public class MainPageServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 2425301522251239666L; + private static final String PROP_AUTHORITY_ID = "authorityId"; + private String mAuthorityId = null; + private String mFormPath = null; + + public MainPageServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + } + + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + + CMS.debug("MainPageServlet process"); + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + try { + form = getTemplate(mFormPath, request, locale); + } catch (IOException e) { + CMS.debug("MainPageServlet process: cant locate the form"); + /* + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + */ + } + + process(argSet, header, ctx, request, response); + + try { + ServletOutputStream out = response.getOutputStream(); + + cmsReq.setStatus(CMSRequest.SUCCESS); + response.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + private void process(CMSTemplateParams argSet, IArgBlock header, + IArgBlock ctx, HttpServletRequest req, HttpServletResponse resp) + throws EBaseException { + + int num = 0; + IArgBlock rarg = null; + IConfigStore cs = CMS.getConfigStore(); + int state = 0; + String host = ""; + String adminInterface = ""; + String eeInterface = ""; + String agentInterface = ""; + try { + state = cs.getInteger("cs.state", 0); + host = cs.getString("machineName", ""); + adminInterface = cs.getString("admin.interface.uri", ""); + eeInterface = cs.getString("ee.interface.uri", ""); + agentInterface = cs.getString("agent.interface.uri", ""); + } catch (Exception e) { + } + + if (state == 0) { + rarg = CMS.createArgBlock(); + rarg.addStringValue("type", "admin"); + rarg.addStringValue("prefix", "http"); + rarg.addIntegerValue("port", + Integer.valueOf(CMS.getEENonSSLPort()).intValue()); + rarg.addStringValue("host", host); + rarg.addStringValue("uri", adminInterface); + argSet.addRepeatRecord(rarg); + num++; + } else if (state == 1) { + if (!eeInterface.equals("")) { + rarg = CMS.createArgBlock(); + rarg.addStringValue("type", "ee"); + rarg.addStringValue("prefix", "https"); + rarg.addIntegerValue("port", + Integer.valueOf(CMS.getEESSLPort()).intValue()); + rarg.addStringValue("host", host); + rarg.addStringValue("uri", eeInterface); + argSet.addRepeatRecord(rarg); + num++; + } + if (!agentInterface.equals("")) { + rarg = CMS.createArgBlock(); + rarg.addStringValue("type", "agent"); + rarg.addStringValue("prefix", "https"); + rarg.addIntegerValue("port", + Integer.valueOf(CMS.getAgentPort()).intValue()); + rarg.addStringValue("host", host); + rarg.addStringValue("uri", agentInterface); + argSet.addRepeatRecord(rarg); + num++; + } + } + header.addIntegerValue("totalRecordCount", num); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ModulePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/ModulePanel.java new file mode 100644 index 000000000..00474615f --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ModulePanel.java @@ -0,0 +1,338 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.TokenException; +import org.mozilla.jss.pkcs11.PK11Module; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.Module; + +public class ModulePanel extends WizardPanelBase { + private CryptoManager mCryptoManager = null; + private Vector<Module> mSupportedModules = null; + private Vector<Module> mOtherModules = null; + private Hashtable<String, PK11Module> mCurrModTable = new Hashtable<String, PK11Module>(); + private WizardServlet mServlet = null; + + public ModulePanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Key Store"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Key Store"); + setId(id); + mServlet = servlet; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putBoolean("preop.ModulePanel.done", false); + } + + public void loadCurrModTable() { + try { + // getting existing modules + mCryptoManager = CryptoManager.getInstance(); + @SuppressWarnings("unchecked") + Enumeration<PK11Module> modules = mCryptoManager.getModules(); + + while (modules.hasMoreElements()) { + PK11Module mod = modules.nextElement(); + + CMS.debug("ModulePanel: got module " + mod.getName()); + mCurrModTable.put(mod.getName(), mod); + } // while + } catch (Exception e) { + CMS.debug( + "ModulePanel: Exception caught in loadCurrModTable: " + + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + } + + /* + * Modules not listed as supported modules + */ + public void loadOtherModules() { + Enumeration<PK11Module> m = mCurrModTable.elements(); + + mOtherModules = new Vector<Module>(); + while (m.hasMoreElements()) { + PK11Module mod = m.nextElement(); + Enumeration<Module> s = mSupportedModules.elements(); + boolean found = false; + + while (s.hasMoreElements()) { + Module sm = s.nextElement(); + + if (mod.getName().equals(sm.getCommonName())) { + found = true; + break; + } else { + found = false; + } + }// while + if (!found) { + // unsupported, use common name as user friendly name + Module module = new Module(mod.getName(), mod.getName()); + + loadModTokens(module, mod); + module.setFound(true); + mOtherModules.addElement(module); + break; + } + }// while + } + + /* + * find all tokens belonging to a module and load the Module + */ + public void loadModTokens(Module module, PK11Module mod) { + @SuppressWarnings("unchecked") + Enumeration<CryptoToken> tokens = mod.getTokens(); + + while (tokens.hasMoreElements()) { + try { + CryptoToken token = tokens.nextElement(); + + CMS.debug("ModulePanel: token nick name=" + token.getName()); + CMS.debug("ModulePanel: token logged in?" + token.isLoggedIn()); + CMS.debug("ModulePanel: token is present?" + token.isPresent()); + if (!token.getName().equals("Internal Crypto Services Token") && + !token.getName().equals("NSS Generic Crypto Services")) { + module.addToken(token); + } else { + CMS.debug( + "ModulePanel: token " + token.getName() + + " not to be added"); + } + + } catch (TokenException ex) { + CMS.debug("ModulePanel:" + ex.toString()); + } + } + } + + /* + * Modules unsupported by the system will not be included + */ + public void loadSupportedModules() { + + // getting supported security modules + // a Vectgor of Modules + mSupportedModules = new Vector<Module>(); + // read from conf store all supported modules + try { + int count = CMS.getConfigStore().getInteger( + "preop.configModules.count"); + + CMS.debug("ModulePanel: supported modules count= " + count); + for (int i = 0; i < count; i++) { + String cn = CMS.getConfigStore().getString( + "preop.configModules.module" + i + ".commonName"); + String pn = CMS.getConfigStore().getString( + "preop.configModules.module" + i + ".userFriendlyName"); + String img = CMS.getConfigStore().getString( + "preop.configModules.module" + i + ".imagePath"); + + if ((cn == null) || (cn.equals(""))) { + break; + } + + CMS.debug("ModulePanel: got from config module: " + cn); + // create a Module object + Module module = new Module(cn, pn, img); + + if (mCurrModTable.containsKey(cn)) { + CMS.debug("ModulePanel: module found: " + cn); + module.setFound(true); + // add token info to module vector + PK11Module m = mCurrModTable.get(cn); + + loadModTokens(module, m); + } + + CMS.debug("ModulePanel: adding module " + cn); + // add module to set + if (!mSupportedModules.contains(module)) { + mSupportedModules.addElement(module); + } + }// for + + } catch (Exception e) { + CMS.debug( + "ModulePanel: Exception caught in loadSupportedModules(): " + + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + } + + public PropertySet getUsage() { + // it a token choice. Available tokens are discovered dynamically so + // can't be a real CHOICE + PropertySet set = new PropertySet(); + + Descriptor tokenDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* default parameter */ + "module token selection"); + + set.add("choice", tokenDesc); + + return set; + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + boolean s = cs.getBoolean("preop.ModulePanel.done", + false); + + if (s != true) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public boolean hasSubPanel() { + return true; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("ModulePanel: display()"); + context.put("title", "Key Store"); + + loadCurrModTable(); + loadSupportedModules(); + loadOtherModules(); + + IConfigStore config = CMS.getConfigStore(); + + try { + String s = config.getString("preop.module.token", + "Internal Key Storage Token"); + + context.put("defTok", s); + } catch (Exception e) { + CMS.debug("ModulePanel:" + e.toString()); + } + + context.put("status", "display"); + context.put("oms", mOtherModules); + context.put("sms", mSupportedModules); + // context.put("status_token", "None"); + String subpanelno = String.valueOf(getPanelNo() + 1); + CMS.debug("ModulePanel subpanelno =" + subpanelno); + context.put("subpanelno", subpanelno); + context.put("panel", "admin/console/config/modulepanel.vm"); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + boolean hasErr = false; + + try { + // get the value of the choice + String select = HttpInput.getID(request, "choice"); + + if (select == null) { + CMS.debug("ModulePanel: no choice selected"); + hasErr = true; + throw new IOException("choice not found"); + } + + IConfigStore config = CMS.getConfigStore(); + String oldtokenname = config.getString("preop.module.token", ""); + if (!oldtokenname.equals(select)) + mServlet.cleanUpFromPanel(mServlet.getPanelNo(request)); + + if (hasErr == false) { + config.putString("preop.module.token", select); + config.putBoolean("preop.ModulePanel.done", true); + } + config.commit(false); + context.put("updateStatus", "success"); + } catch (Exception e) { + CMS.debug("ModulePanel: Exception caught: " + e.toString()); + System.err.println("Exception caught: " + e.toString()); + context.put("updateStatus", "failure"); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Security Module"); + context.put("panel", "admin/console/config/modulepanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ModuleServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/ModuleServlet.java new file mode 100644 index 000000000..1c67654b4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/ModuleServlet.java @@ -0,0 +1,90 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; + +public class ModuleServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = 6518965840466227888L; + + /** + * Collect information on where keys are to be generated. + * Once collected, write to CS.cfg: + * "preop.module=soft" + * or + * "preop.module=hard" + * + * <ul> + * <li>http.param selection "soft" or "hard" for software token or hardware token + * </ul> + */ + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + Template template = null; + + CMS.debug("ModuleServlet: in ModuleServlet"); + try { + + // get the value of the selection + String selection = request.getParameter("selection"); + + if (selection != null) { + + if (selection.equals("soft")) { + CMS.debug("ModuleServlet: user selected software"); + // XXX + CMS.getConfigStore().putString("preop.module", "soft"); + CMS.getConfigStore().commit(false); + response.sendRedirect("size"); + } else if (selection.equals("hard")) { + CMS.debug("ModuleServlet: user selected hardware"); + // YYY + CMS.getConfigStore().putString("preop.module", "hard"); + CMS.getConfigStore().commit(false); + response.sendRedirect("size"); + } else { + CMS.debug("ModuleServlet: illegal selection: " + selection); + context.put("error", "failed selection"); + } + + } else { + CMS.debug("ModuleServlet: no selection"); + } + + template = Velocity.getTemplate("admin/console/config/module.vm"); + } catch (Exception e) { + CMS.debug("ModuleServlet: Exception caught: " + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/NamePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/NamePanel.java new file mode 100644 index 000000000..916ab199b --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/NamePanel.java @@ -0,0 +1,993 @@ +// --- 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.csadmin; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.URL; +import java.net.URLEncoder; +import java.util.Enumeration; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509Key; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class NamePanel extends WizardPanelBase { + private Vector<Cert> mCerts = null; + private WizardServlet mServlet = null; + + public NamePanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Subject Names"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Subject Names"); + setId(id); + mServlet = servlet; + } + + /** + * Returns the usage.XXX usage needs to be made dynamic + */ + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + Descriptor caDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "CA Signing Certificate's DN"); + + set.add("caDN", caDN); + + Descriptor sslDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "SSL Server Certificate's DN"); + + set.add("sslDN", sslDN); + + Descriptor subsystemDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "CA Subsystem Certificate's DN"); + + set.add("subsystemDN", subsystemDN); + + Descriptor ocspDN = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "OCSP Signing Certificate's DN"); + + set.add("ocspDN", ocspDN); + + return set; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + try { + @SuppressWarnings("unused") + boolean done = cs.getBoolean("preop.NamePanel.done"); // check for errors + cs.putBoolean("preop.NamePanel.done", false); + cs.commit(false); + } catch (Exception e) { + } + + String list = ""; + try { + list = cs.getString("preop.cert.list", ""); + } catch (Exception e) { + } + + StringTokenizer st = new StringTokenizer(list, ","); + while (st.hasMoreTokens()) { + String t = st.nextToken(); + cs.remove("preop.cert." + t + ".done"); + } + + try { + cs.commit(false); + } catch (Exception e) { + } + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + boolean s = cs.getBoolean("preop.NamePanel.done", false); + if (s != true) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public String capitalize(String s) { + if (s.length() == 0) { + return s; + } else { + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("NamePanel: display()"); + context.put("title", "Subject Names"); + + // update session id + String session_id = request.getParameter("session_id"); + if (session_id != null) { + CMS.debug("NamePanel setting session id."); + CMS.setConfigSDSessionId(session_id); + } + + mCerts = new Vector<Cert>(); + + String domainname = ""; + IConfigStore config = CMS.getConfigStore(); + String select = ""; + String hselect = ""; + String cstype = ""; + try { + //if CA, at the hierarchy panel, was it root or subord? + hselect = config.getString("preop.hierarchy.select", ""); + select = config.getString("preop.subsystem.select", ""); + cstype = config.getString("cs.type", ""); + context.put("select", select); + if (cstype.equals("CA") && hselect.equals("root")) { + CMS.debug("NamePanel ca is root"); + context.put("isRoot", "true"); + } else { + CMS.debug("NamePanel not ca or not root"); + context.put("isRoot", "false"); + } + } catch (Exception e) { + } + + try { + domainname = config.getString("securitydomain.name", ""); + + String certTags = config.getString("preop.cert.list"); + // same token for now + String token = config.getString(PRE_CONF_CA_TOKEN); + StringTokenizer st = new StringTokenizer(certTags, ","); + String domaintype = config.getString("securitydomain.select"); + int count = 0; + String host = ""; + int sd_admin_port = -1; + if (domaintype.equals("existing")) { + host = config.getString("securitydomain.host", ""); + sd_admin_port = config.getInteger("securitydomain.httpsadminport", -1); + count = getSubsystemCount(host, sd_admin_port, true, cstype); + } + + while (st.hasMoreTokens()) { + String certTag = st.nextToken(); + + CMS.debug("NamePanel: display() about to process certTag :" + certTag); + String nn = config.getString( + PCERT_PREFIX + certTag + ".nickname"); + Cert c = new Cert(token, nn, certTag); + String userfriendlyname = config.getString( + PCERT_PREFIX + certTag + ".userfriendlyname"); + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + + c.setUserFriendlyName(userfriendlyname); + + String type = config.getString(PCERT_PREFIX + certTag + ".type"); + c.setType(type); + boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true); + c.setEnable(enable); + + String cert = config.getString(subsystem + "." + certTag + ".cert", ""); + String certreq = + config.getString(subsystem + "." + certTag + ".certreq", ""); + + String dn = config.getString(PCERT_PREFIX + certTag + ".dn"); + boolean override = config.getBoolean(PCERT_PREFIX + certTag + + ".cncomponent.override", true); + //o_sd is to add o=secritydomainname + boolean o_sd = config.getBoolean(PCERT_PREFIX + certTag + + "o_securitydomain", true); + domainname = config.getString("securitydomain.name", ""); + CMS.debug("NamePanel: display() override is " + override); + CMS.debug("NamePanel: display() o_securitydomain is " + o_sd); + CMS.debug("NamePanel: display() domainname is " + domainname); + + boolean dnUpdated = false; + try { + dnUpdated = config.getBoolean(PCERT_PREFIX + certTag + ".updatedDN"); + } catch (Exception e) { + } + + try { + @SuppressWarnings("unused") + boolean done = config.getBoolean("preop.NamePanel.done"); // check for errors + c.setDN(dn); + } catch (Exception e) { + String instanceId = config.getString("service.instanceID", ""); + if (select.equals("clone") || dnUpdated) { + c.setDN(dn); + } else if (count != 0 && override && (cert.equals("") || certreq.equals(""))) { + CMS.debug("NamePanel subsystemCount = " + count); + c.setDN(dn + " " + count + + ((!instanceId.equals("")) ? (",OU=" + instanceId) : "") + + ((o_sd) ? (",O=" + domainname) : "")); + config.putBoolean(PCERT_PREFIX + certTag + ".updatedDN", true); + } else { + c.setDN(dn + + ((!instanceId.equals("")) ? (",OU=" + instanceId) : "") + + ((o_sd) ? (",O=" + domainname) : "")); + config.putBoolean(PCERT_PREFIX + certTag + ".updatedDN", true); + } + } + + mCerts.addElement(c); + CMS.debug( + "NamePanel: display() added cert to mCerts: certTag " + + certTag); + config.putString(PCERT_PREFIX + c.getCertTag() + ".dn", c.getDN()); + }// while + } catch (EBaseException e) { + CMS.debug("NamePanel: display() exception caught:" + e.toString()); + } catch (Exception e) { + CMS.debug("NamePanel: " + e.toString()); + } + + CMS.debug("NamePanel: Ready to get SSL EE HTTPS urls"); + Vector<String> v = getUrlListFromSecurityDomain(config, "CA", "SecurePort"); + v.addElement("External CA"); + StringBuffer list = new StringBuffer(); + int size = v.size(); + + for (int i = 0; i < size; i++) { + if (i == size - 1) { + list.append(v.elementAt(i)); + } else { + list.append(v.elementAt(i)); + list.append(","); + } + } + + try { + config.putString("preop.ca.list", list.toString()); + config.commit(false); + } catch (Exception e) { + } + + context.put("urls", v); + + context.put("certs", mCerts); + context.put("panel", "admin/console/config/namepanel.vm"); + context.put("errorString", ""); + + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + Enumeration<Cert> c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = c.nextElement(); + // get the dn's and put in config + if (cert.isEnable()) { + String dn = HttpInput.getDN(request, cert.getCertTag()); + + if (dn == null || dn.length() == 0) { + context.put("updateStatus", "validate-failure"); + throw new IOException("Empty DN for " + cert.getUserFriendlyName()); + } + } + } // while + } + + /* + * update some parameters for clones + */ + public void updateCloneConfig(IConfigStore config) + throws EBaseException, IOException { + String cstype = config.getString("cs.type", null); + cstype = toLowerCaseSubsystemType(cstype); + if (cstype.equals("kra")) { + String token = config.getString(PRE_CONF_CA_TOKEN); + if (!token.equals("Internal Key Storage Token")) { + CMS.debug("NamePanel: updating configuration for KRA clone with hardware token"); + String subsystem = config.getString(PCERT_PREFIX + "storage.subsystem"); + String storageNickname = getNickname(config, "storage"); + String transportNickname = getNickname(config, "transport"); + + config.putString(subsystem + ".storageUnit.hardware", token); + config.putString(subsystem + ".storageUnit.nickName", token + ":" + storageNickname); + config.putString(subsystem + ".transportUnit.nickName", token + ":" + transportNickname); + config.commit(false); + } else { // software token + // parameters already set + } + } + + // audit signing cert + String audit_nn = config.getString(cstype + ".audit_signing" + ".nickname", ""); + String audit_tk = config.getString(cstype + ".audit_signing" + ".tokenname", ""); + if (!audit_tk.equals("Internal Key Storage Token") && !audit_tk.equals("")) { + config.putString("log.instance.SignedAudit.signedAuditCertNickname", + audit_tk + ":" + audit_nn); + } else { + config.putString("log.instance.SignedAudit.signedAuditCertNickname", + audit_nn); + } + } + + /* + * get some of the "preop" parameters to persisting parameters + */ + public void updateConfig(IConfigStore config, String certTag) + throws EBaseException, IOException { + String token = config.getString(PRE_CONF_CA_TOKEN); + String subsystem = config.getString(PCERT_PREFIX + certTag + ".subsystem"); + CMS.debug("NamePanel: subsystem " + subsystem); + String nickname = getNickname(config, certTag); + + CMS.debug("NamePanel: updateConfig() for certTag " + certTag); + // XXX these two are used throughout the CA so have to write them + // should change the entire system to use the uniformed names later + if (certTag.equals("signing") || certTag.equals("ocsp_signing")) { + CMS.debug("NamePanel: setting signing nickname=" + nickname); + config.putString(subsystem + "." + certTag + ".cacertnickname", nickname); + config.putString(subsystem + "." + certTag + ".certnickname", nickname); + } + + // if KRA, hardware token needs param "kra.storageUnit.hardware" in CS.cfg + String cstype = config.getString("cs.type", null); + cstype = toLowerCaseSubsystemType(cstype); + if (cstype.equals("kra")) { + if (!token.equals("Internal Key Storage Token")) { + if (certTag.equals("storage")) { + config.putString(subsystem + ".storageUnit.hardware", token); + config.putString(subsystem + ".storageUnit.nickName", token + ":" + nickname); + } else if (certTag.equals("transport")) { + config.putString(subsystem + ".transportUnit.nickName", token + ":" + nickname); + } + } else { // software token + if (certTag.equals("storage")) { + config.putString(subsystem + ".storageUnit.nickName", nickname); + } else if (certTag.equals("transport")) { + config.putString(subsystem + ".transportUnit.nickName", nickname); + } + } + } + + String serverCertNickname = nickname; + String path = CMS.getConfigStore().getString("instanceRoot", ""); + if (certTag.equals("sslserver")) { + if (!token.equals("Internal Key Storage Token")) { + serverCertNickname = token + ":" + nickname; + } + PrintStream ps = new PrintStream(new FileOutputStream(path + "/conf/serverCertNick.conf")); + ps.println(serverCertNickname); + ps.close(); + } + + config.putString(subsystem + "." + certTag + ".nickname", nickname); + config.putString(subsystem + "." + certTag + ".tokenname", token); + if (certTag.equals("audit_signing")) { + if (!token.equals("Internal Key Storage Token") && !token.equals("")) { + config.putString("log.instance.SignedAudit.signedAuditCertNickname", + token + ":" + nickname); + } else { + config.putString("log.instance.SignedAudit.signedAuditCertNickname", + nickname); + } + } + /* + config.putString(CERT_PREFIX + certTag + ".defaultSigningAlgorithm", + "SHA1withRSA"); + */ + + // for system certs verification + if (!token.equals("Internal Key Storage Token") && !token.equals("")) { + config.putString(subsystem + ".cert." + certTag + ".nickname", + token + ":" + nickname); + } else { + config.putString(subsystem + ".cert." + certTag + ".nickname", nickname); + } + + config.commit(false); + CMS.debug("NamePanel: updateConfig() done"); + } + + /** + * create and sign a cert locally (handles both "selfsign" and "local") + */ + public void configCert(HttpServletRequest request, + HttpServletResponse response, + Context context, Cert certObj) throws IOException { + CMS.debug("NamePanel: configCert called"); + + IConfigStore config = CMS.getConfigStore(); + String caType = certObj.getType(); + CMS.debug("NamePanel: in configCert caType is " + caType); + X509CertImpl cert = null; + String certTag = certObj.getCertTag(); + + try { + updateConfig(config, certTag); + if (caType.equals("remote")) { + String v = config.getString("preop.ca.type", ""); + + CMS.debug("NamePanel configCert: remote CA"); + String pkcs10 = CertUtil.getPKCS10(config, PCERT_PREFIX, + certObj, context); + certObj.setRequest(pkcs10); + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + config.putString(subsystem + "." + certTag + ".certreq", pkcs10); + String profileId = config.getString(PCERT_PREFIX + certTag + ".profile"); + String session_id = CMS.getConfigSDSessionId(); + String sd_hostname = ""; + int sd_ee_port = -1; + try { + sd_hostname = config.getString("securitydomain.host", ""); + sd_ee_port = config.getInteger("securitydomain.httpseeport", -1); + } catch (Exception ee) { + CMS.debug("NamePanel: configCert() exception caught:" + ee.toString()); + } + String sysType = config.getString("cs.type", ""); + String machineName = config.getString("machineName", ""); + String securePort = config.getString("service.securePort", ""); + if (certTag.equals("subsystem")) { + String content = + "requestor_name=" + + sysType + "-" + machineName + "-" + securePort + "&profileId=" + profileId + + "&cert_request_type=pkcs10&cert_request=" + URLEncoder.encode(pkcs10, "UTF-8") + + "&xmlOutput=true&sessionID=" + session_id; + cert = CertUtil.createRemoteCert(sd_hostname, sd_ee_port, + content, response, this); + if (cert == null) { + throw new IOException("Error: remote certificate is null"); + } + } else if (v.equals("sdca")) { + String ca_hostname = ""; + int ca_port = -1; + try { + ca_hostname = config.getString("preop.ca.hostname", ""); + ca_port = config.getInteger("preop.ca.httpsport", -1); + } catch (Exception ee) { + } + + String content = + "requestor_name=" + + sysType + "-" + machineName + "-" + securePort + "&profileId=" + profileId + + "&cert_request_type=pkcs10&cert_request=" + URLEncoder.encode(pkcs10, "UTF-8") + + "&xmlOutput=true&sessionID=" + session_id; + cert = CertUtil.createRemoteCert(ca_hostname, ca_port, + content, response, this); + if (cert == null) { + throw new IOException("Error: remote certificate is null"); + } + } else if (v.equals("otherca")) { + config.putString(subsystem + "." + certTag + ".cert", + "...paste certificate here..."); + } else { + CMS.debug("NamePanel: no preop.ca.type is provided"); + } + } else { // not remote CA, ie, self-signed or local + ISubsystem ca = CMS.getSubsystem(ICertificateAuthority.ID); + + if (ca == null) { + String s = PCERT_PREFIX + certTag + ".type"; + + CMS.debug( + "The value for " + s + + " should be remote, nothing else."); + throw new IOException( + "The value for " + s + " should be remote"); + } + + String pubKeyType = config.getString( + PCERT_PREFIX + certTag + ".keytype"); + if (pubKeyType.equals("rsa")) { + + String pubKeyModulus = config.getString( + PCERT_PREFIX + certTag + ".pubkey.modulus"); + String pubKeyPublicExponent = config.getString( + PCERT_PREFIX + certTag + ".pubkey.exponent"); + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + + if (certTag.equals("signing")) { + X509Key x509key = CryptoUtil.getPublicX509Key( + CryptoUtil.string2byte(pubKeyModulus), + CryptoUtil.string2byte(pubKeyPublicExponent)); + + cert = CertUtil.createLocalCert(config, x509key, + PCERT_PREFIX, certTag, caType, context); + } else { + String cacert = config.getString("ca.signing.cert", ""); + + if (cacert.equals("") || cacert.startsWith("...")) { + certObj.setCert( + "...certificate be generated internally..."); + config.putString(subsystem + "." + certTag + ".cert", + "...certificate be generated internally..."); + } else { + X509Key x509key = CryptoUtil.getPublicX509Key( + CryptoUtil.string2byte(pubKeyModulus), + CryptoUtil.string2byte(pubKeyPublicExponent)); + + cert = CertUtil.createLocalCert(config, x509key, + PCERT_PREFIX, certTag, caType, context); + } + } + } else if (pubKeyType.equals("ecc")) { + String pubKeyEncoded = config.getString( + PCERT_PREFIX + certTag + ".pubkey.encoded"); + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + + if (certTag.equals("signing")) { + + X509Key x509key = CryptoUtil.getPublicX509ECCKey(CryptoUtil.string2byte(pubKeyEncoded)); + cert = CertUtil.createLocalCert(config, x509key, + PCERT_PREFIX, certTag, caType, context); + } else { + String cacert = config.getString("ca.signing.cert", ""); + + if (cacert.equals("") || cacert.startsWith("...")) { + certObj.setCert( + "...certificate be generated internally..."); + config.putString(subsystem + "." + certTag + ".cert", + "...certificate be generated internally..."); + } else { + X509Key x509key = CryptoUtil.getPublicX509ECCKey( + CryptoUtil.string2byte(pubKeyEncoded)); + + cert = CertUtil.createLocalCert(config, x509key, + PCERT_PREFIX, certTag, caType, context); + } + } + } else { + // invalid key type + CMS.debug("Invalid key type " + pubKeyType); + } + if (cert != null) { + if (certTag.equals("subsystem")) + CertUtil.addUserCertificate(cert); + } + } // done self-signed or local + + if (cert != null) { + byte[] certb = cert.getEncoded(); + String certs = CryptoUtil.base64Encode(certb); + + // certObj.setCert(certs); + String subsystem = config.getString( + PCERT_PREFIX + certTag + ".subsystem"); + config.putString(subsystem + "." + certTag + ".cert", certs); + } + config.commit(false); + } catch (IOException e) { + throw e; + } catch (Exception e) { + CMS.debug("NamePanel configCert() exception caught:" + e.toString()); + } + } + + public void configCertWithTag(HttpServletRequest request, + HttpServletResponse response, + Context context, String tag) throws IOException { + CMS.debug("NamePanel: configCertWithTag start"); + Enumeration<Cert> c = mCerts.elements(); + IConfigStore config = CMS.getConfigStore(); + + while (c.hasMoreElements()) { + Cert cert = c.nextElement(); + String ct = cert.getCertTag(); + CMS.debug("NamePanel: configCertWithTag ct=" + ct + + " tag=" + tag); + if (ct.equals(tag)) { + try { + String nickname = HttpInput.getNickname(request, ct + "_nick"); + if (nickname != null) { + CMS.debug("configCertWithTag: Setting nickname for " + ct + " to " + nickname); + config.putString(PCERT_PREFIX + ct + ".nickname", nickname); + cert.setNickname(nickname); + config.commit(false); + } + String dn = HttpInput.getDN(request, ct); + if (dn != null) { + config.putString(PCERT_PREFIX + ct + ".dn", dn); + config.commit(false); + } + } catch (Exception e) { + CMS.debug("NamePanel: configCertWithTag: Exception in setting nickname for " + + ct + ": " + e.toString()); + } + + configCert(request, response, context, cert); + CMS.debug("NamePanel: configCertWithTag done with tag=" + tag); + return; + } + } + CMS.debug("NamePanel: configCertWithTag done"); + } + + private boolean inputChanged(HttpServletRequest request) + throws IOException { + IConfigStore config = CMS.getConfigStore(); + + boolean hasChanged = false; + try { + Enumeration<Cert> c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = c.nextElement(); + String ct = cert.getCertTag(); + boolean enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true); + if (!enable) + continue; + + String olddn = config.getString(PCERT_PREFIX + cert.getCertTag() + ".dn", ""); + // get the dn's and put in config + String dn = HttpInput.getDN(request, cert.getCertTag()); + + if (!olddn.equals(dn)) + hasChanged = true; + + String oldnick = config.getString(PCERT_PREFIX + ct + ".nickname"); + String nick = HttpInput.getNickname(request, ct + "_nick"); + if (!oldnick.equals(nick)) + hasChanged = true; + + } + } catch (Exception e) { + } + + return hasChanged; + } + + public String getURL(HttpServletRequest request, IConfigStore config) { + String index = request.getParameter("urls"); + if (index == null) { + return null; + } + String url = ""; + if (index.startsWith("http")) { + // user may submit url directlry + url = index; + } else { + try { + int x = Integer.parseInt(index); + String list = config.getString("preop.ca.list", ""); + StringTokenizer tokenizer = new StringTokenizer(list, ","); + int counter = 0; + + while (tokenizer.hasMoreTokens()) { + url = tokenizer.nextToken(); + if (counter == x) { + break; + } + counter++; + } + } catch (Exception e) { + } + } + return url; + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + CMS.debug("NamePanel: in update()"); + boolean hasErr = false; + + if (inputChanged(request)) { + mServlet.cleanUpFromPanel(mServlet.getPanelNo(request)); + } else if (isPanelDone()) { + context.put("updateStatus", "success"); + return; + } + + IConfigStore config = CMS.getConfigStore(); + + String hselect = ""; + ISubsystem subsystem = CMS.getSubsystem(ICertificateAuthority.ID); + try { + //if CA, at the hierarchy panel, was it root or subord? + hselect = config.getString("preop.hierarchy.select", ""); + String cstype = config.getString("preop.subsystem.select", ""); + if (cstype.equals("clone")) { + CMS.debug("NamePanel: clone configuration detected"); + // still need to handle SSL certificate + configCertWithTag(request, response, context, "sslserver"); + String url = getURL(request, config); + if (url != null && !url.equals("External CA")) { + // preop.ca.url and admin port are required for setting KRA connector + url = url.substring(url.indexOf("https")); + config.putString("preop.ca.url", url); + + URL urlx = new URL(url); + updateCloneSDCAInfo(request, context, urlx.getHost(), + Integer.toString(urlx.getPort())); + + } + updateCloneConfig(config); + CMS.debug("NamePanel: clone configuration done"); + context.put("updateStatus", "success"); + return; + } + } catch (Exception e) { + CMS.debug("NamePanel: configCertWithTag failure - " + e); + context.put("updateStatus", "failure"); + return; + } + + //if no hselect, then not CA + if (hselect.equals("") || hselect.equals("join")) { + String url = getURL(request, config); + + URL urlx = null; + + if (url.equals("External CA")) { + CMS.debug("NamePanel: external CA selected"); + config.putString("preop.ca.type", "otherca"); + if (subsystem != null) { + config.putString(PCERT_PREFIX + "signing.type", "remote"); + } + + config.putString("preop.ca.pkcs7", ""); + config.putInteger("preop.ca.certchain.size", 0); + context.put("check_otherca", "checked"); + CMS.debug("NamePanel: update: this is the external CA."); + } else { + CMS.debug("NamePanel: local CA selected"); + // parse URL (CA1 - https://...) + url = url.substring(url.indexOf("https")); + config.putString("preop.ca.url", url); + + urlx = new URL(url); + config.putString("preop.ca.type", "sdca"); + CMS.debug("NamePanel: update: this is a CA in the security domain."); + context.put("check_sdca", "checked"); + sdca(request, context, urlx.getHost(), + Integer.toString(urlx.getPort())); + if (subsystem != null) { + config.putString(PCERT_PREFIX + "signing.type", "remote"); + config.putString(PCERT_PREFIX + "signing.profile", + "caInstallCACert"); + } + } + + try { + config.commit(false); + } catch (Exception e) { + } + + } + + try { + + Enumeration<Cert> c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = c.nextElement(); + String ct = cert.getCertTag(); + boolean enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true); + if (!enable) + continue; + + boolean certDone = config.getBoolean(PCERT_PREFIX + ct + ".done", false); + if (certDone) + continue; + + // get the nicknames and put in config + String nickname = HttpInput.getNickname(request, ct + "_nick"); + if (nickname != null) { + CMS.debug("NamePanel: update: Setting nickname for " + ct + " to " + nickname); + config.putString(PCERT_PREFIX + ct + ".nickname", nickname); + cert.setNickname(nickname); + } else { + nickname = cert.getNickname(); + } + + // get the dn's and put in config + String dn = HttpInput.getDN(request, ct); + + config.putString(PCERT_PREFIX + ct + ".dn", dn); + // commit here in case it changes + config.commit(false); + + try { + configCert(request, response, context, cert); + config.putBoolean("preop.cert." + cert.getCertTag() + ".done", + true); + config.commit(false); + } catch (Exception e) { + CMS.debug( + "NamePanel: update() exception caught:" + + e.toString()); + hasErr = true; + System.err.println("Exception caught: " + e.toString()); + } + + } // while + if (hasErr == false) { + config.putBoolean("preop.NamePanel.done", true); + config.commit(false); + } + + } catch (Exception e) { + CMS.debug("NamePanel: Exception caught: " + e.toString()); + System.err.println("Exception caught: " + e.toString()); + }// try + + try { + config.commit(false); + } catch (Exception e) { + } + + if (!hasErr) { + context.put("updateStatus", "success"); + } else { + context.put("updateStatus", "failure"); + } + CMS.debug("NamePanel: update() done"); + } + + private void updateCloneSDCAInfo(HttpServletRequest request, Context context, String hostname, String httpsPortStr) + throws IOException { + CMS.debug("NamePanel updateCloneSDCAInfo: selected CA hostname=" + hostname + " port=" + httpsPortStr); + String https_admin_port = ""; + IConfigStore config = CMS.getConfigStore(); + + if (hostname == null || hostname.length() == 0) { + context.put("errorString", "Hostname is null"); + throw new IOException("Hostname is null"); + } + + // Retrieve the associated HTTPS Admin port so that it + // may be stored for use with ImportAdminCertPanel + https_admin_port = getSecurityDomainAdminPort(config, + hostname, + httpsPortStr, + "CA"); + + try { + Integer.parseInt(httpsPortStr); // check for errors + } catch (Exception e) { + CMS.debug( + "NamePanel update: Https port is not valid. Exception: " + + e.toString()); + throw new IOException("Https Port is not valid."); + } + + config.putString("preop.ca.hostname", hostname); + config.putString("preop.ca.httpsport", httpsPortStr); + config.putString("preop.ca.httpsadminport", https_admin_port); + } + + private void sdca(HttpServletRequest request, Context context, String hostname, String httpsPortStr) + throws IOException { + CMS.debug("NamePanel update: this is the CA in the security domain."); + CMS.debug("NamePanel update: selected CA hostname=" + hostname + " port=" + httpsPortStr); + String https_admin_port = ""; + IConfigStore config = CMS.getConfigStore(); + + context.put("sdcaHostname", hostname); + context.put("sdHttpPort", httpsPortStr); + + if (hostname == null || hostname.length() == 0) { + context.put("errorString", "Hostname is null"); + throw new IOException("Hostname is null"); + } + + // Retrieve the associated HTTPS Admin port so that it + // may be stored for use with ImportAdminCertPanel + https_admin_port = getSecurityDomainAdminPort(config, + hostname, + httpsPortStr, + "CA"); + + int httpsport = -1; + + try { + httpsport = Integer.parseInt(httpsPortStr); + } catch (Exception e) { + CMS.debug( + "NamePanel update: Https port is not valid. Exception: " + + e.toString()); + throw new IOException("Https Port is not valid."); + } + + config.putString("preop.ca.hostname", hostname); + config.putString("preop.ca.httpsport", httpsPortStr); + config.putString("preop.ca.httpsadminport", https_admin_port); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + updateCertChainUsingSecureEEPort(config, "ca", hostname, + httpsport, true, context, + certApprovalCallback); + try { + CMS.debug("Importing CA chain"); + importCertChain("ca"); + } catch (Exception e1) { + CMS.debug("Failed in importing CA chain"); + } + } + + public void initParams(HttpServletRequest request, Context context) + throws IOException { + context.put("certs", mCerts); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + try { + initParams(request, context); + } catch (IOException e) { + } + context.put("title", "Subject Names"); + context.put("panel", "admin/console/config/namepanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java b/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java new file mode 100644 index 000000000..0042cdb5a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java @@ -0,0 +1,331 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +import org.w3c.dom.Node; + +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.usrgrp.ICertUserLocator; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.util.Utils; +import com.netscape.cmsutil.xml.XMLObject; + +/** + * This servlet creates a TPS user in the CA, + * and it associates TPS's server certificate to + * the user. Finally, it addes the user to the + * administrator group. This procedure will + * allows TPS to connect to the CA for certificate + * issuance. + */ +public class RegisterUser extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -699307373400031138L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + private String mGroupName = null; + private final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE = + "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3"; + + public RegisterUser() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("RegisterUser: initializing..."); + super.init(sc); + CMS.debug("RegisterUser: done initializing..."); + mGroupName = sc.getInitParameter("GroupName"); + CMS.debug("RegisterUser: group name " + mGroupName); + } + + /** + * Process the HTTP request. + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("UpdateUpdater: processing..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = null; + try { + authToken = authenticate(cmsReq); + CMS.debug("RegisterUser authentication successful."); + } catch (Exception e) { + CMS.debug("RegisterUser: authentication failed."); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + if (authToken == null) { + CMS.debug("RegisterUser: authentication failed."); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + AuthzToken authzToken = null; + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, + "modify"); + CMS.debug("RegisterUser authorization successful."); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + "Error: Encountered problem during authorization."); + return; + } + + if (authzToken == null) { + outputError(httpResp, "Error: Not authorized"); + return; + } + + // create user and add certificate + String uid = httpReq.getParameter("uid"); + String name = httpReq.getParameter("name"); + String certsString = httpReq.getParameter("certificate"); + CMS.debug("RegisterUser got uid=" + uid); + CMS.debug("RegisterUser got name=" + name); + CMS.debug("RegisterUser got certsString=" + certsString); + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditParams = "Scope;;users+Operation;;OP_ADD+source;;RegisterUser" + + "+Resource;;" + uid + + "+fullname;;" + name + + "+state;;1" + + "+userType;;<null>+email;;<null>+password;;<null>+phone;;<null>"; + + IUGSubsystem ugsys = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + + IUser user = null; + boolean foundByCert = false; + X509Certificate certs[] = new X509Certificate[1]; + try { + + byte bCert[] = null; + X509CertImpl cert = null; + bCert = Utils.base64decode(certsString); + cert = new X509CertImpl(bCert); + certs[0] = (X509Certificate) cert; + + // test to see if the cert already belongs to a user + ICertUserLocator cul = ugsys.getCertUserLocator(); + com.netscape.certsrv.usrgrp.Certificates c = + new com.netscape.certsrv.usrgrp.Certificates(certs); + user = (IUser) cul.locateUser(c); + } catch (Exception ec) { + CMS.debug("RegisterUser: exception thrown: " + ec.toString()); + } + if (user == null) { + CMS.debug("RegisterUser NOT found user by cert"); + try { + user = ugsys.getUser(uid); + CMS.debug("RegisterUser found user by uid " + uid); + } catch (Exception eee) { + } + } else { + foundByCert = true; + CMS.debug("RegisterUser found user by cert"); + } + + try { + + if (user == null) { + // create user only if such user does not exist + user = ugsys.createUser(uid); + user.setFullName(name); + user.setState("1"); + user.setUserType(""); + user.setEmail(""); + user.setPhone(""); + user.setPassword(""); + + ugsys.addUser(user); + CMS.debug("RegisterUser created user " + uid); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams); + audit(auditMessage); + } + + // extract all line separators + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < certsString.length(); i++) { + if (!Character.isWhitespace(certsString.charAt(i))) { + sb.append(certsString.charAt(i)); + } + } + certsString = sb.toString(); + + auditParams = "Scope;;certs+Operation;;OP_ADD+source;;RegisterUser" + + "+Resource;;" + uid + + "+cert;;" + certsString; + + user.setX509Certificates(certs); + if (!foundByCert) { + ugsys.addUserCert(user); + CMS.debug("RegisterUser added user certificate"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams); + audit(auditMessage); + } else + CMS.debug("RegisterUser no need to add user certificate"); + } catch (Exception eee) { + CMS.debug("RegisterUser error " + eee.toString()); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams); + + audit(auditMessage); + outputError(httpResp, "Error: Certificate malformed"); + return; + } + + // add user to the group + auditParams = "Scope;;groups+Operation;;OP_MODIFY+source;;RegisterUser" + + "+Resource;;" + mGroupName; + try { + Enumeration<IGroup> groups = ugsys.findGroups(mGroupName); + IGroup group = groups.nextElement(); + + auditParams += "+user;;"; + Enumeration<String> members = group.getMemberNames(); + while (members.hasMoreElements()) { + auditParams += members.nextElement(); + if (members.hasMoreElements()) { + auditParams += ","; + } + } + + if (!group.isMember(user.getUserID())) { + auditParams += "," + user.getUserID(); + group.addMemberName(user.getUserID()); + ugsys.modifyGroup(group); + CMS.debug("RegisterUser modified group"); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + auditParams); + + audit(auditMessage); + } + } catch (Exception e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + auditParams); + + audit(auditMessage); + } + + // send success status back to the requestor + try { + CMS.debug("RegisterUser: Sending response"); + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("RegisterUser: Failed to send the XML output"); + } + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java new file mode 100644 index 000000000..54a5ed3f6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java @@ -0,0 +1,718 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.csadmin; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.Principal; +import java.security.PublicKey; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPDN; +import netscape.security.x509.X509CertImpl; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.BMPString; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.crypto.Cipher; +import org.mozilla.jss.crypto.CryptoStore; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.EncryptionAlgorithm; +import org.mozilla.jss.crypto.IVParameterSpec; +import org.mozilla.jss.crypto.InternalCertificate; +import org.mozilla.jss.crypto.KeyGenAlgorithm; +import org.mozilla.jss.crypto.KeyGenerator; +import org.mozilla.jss.crypto.KeyWrapAlgorithm; +import org.mozilla.jss.crypto.KeyWrapper; +import org.mozilla.jss.crypto.SymmetricKey; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.pkcs11.PK11Store; +import org.mozilla.jss.pkcs12.AuthenticatedSafes; +import org.mozilla.jss.pkcs12.CertBag; +import org.mozilla.jss.pkcs12.PFX; +import org.mozilla.jss.pkcs12.PasswordConverter; +import org.mozilla.jss.pkcs12.SafeBag; +import org.mozilla.jss.pkix.primitive.Attribute; +import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo; +import org.mozilla.jss.pkix.primitive.PrivateKeyInfo; +import org.mozilla.jss.util.Password; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class RestoreKeyCertPanel extends WizardPanelBase { + + public RestoreKeyCertPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Import Keys and Certificates"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Import Keys and Certificates"); + setId(id); + } + + /** + * Should we skip this panel for the configuration. + */ + public boolean shouldSkip() { + CMS.debug("RestoreKeyCertPanel: should skip"); + + IConfigStore cs = CMS.getConfigStore(); + // if we are root, no need to get the certificate chain. + + try { + String select = cs.getString("preop.subsystem.select", ""); + if (select.equals("clone")) { + return false; + } + } catch (EBaseException e) { + } + + return true; + } + + public boolean isSubPanel() { + return true; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + /* clean up if necessary */ + try { + @SuppressWarnings("unused") + boolean done = cs.getBoolean("preop.restorekeycert.done"); // check for errors + cs.putBoolean("preop.restorekeycert.done", false); + cs.commit(false); + } catch (Exception e) { + } + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.restorekeycert.done", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Import Keys and Certificates"); + IConfigStore config = CMS.getConfigStore(); + + if (isPanelDone()) { + + try { + String s = config.getString("preop.pk12.path", ""); + context.put("path", s); + } catch (Exception e) { + CMS.debug(e.toString()); + } + } else { + context.put("path", ""); + } + + context.put("password", ""); + context.put("panel", "admin/console/config/restorekeycertpanel.vm"); + context.put("errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + String tokenname = ""; + try { + tokenname = config.getString("preop.module.token", ""); + } catch (Exception e) { + } + + if (!tokenname.equals("Internal Key Storage Token")) + return; + + // Path can be empty. If this case, we just want to + // get to the next panel. Customer has HSM. + String s = HttpInput.getString(request, "path"); + // if (s == null || s.equals("")) { + // CMS.debug("RestoreKeyCertPanel validate: path is empty"); + // throw new IOException("Path is empty"); + // } + + if (s != null && !s.equals("")) { + s = HttpInput.getPassword(request, "__password"); + if (s == null || s.equals("")) { + CMS.debug("RestoreKeyCertPanel validate: password is empty"); + context.put("updateStatus", "validate-failure"); + throw new IOException("Empty password"); + } + } + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore config = CMS.getConfigStore(); + String path = HttpInput.getString(request, "path"); + if (path == null || path.equals("")) { + // skip to next panel + config.putBoolean("preop.restorekeycert.done", true); + try { + config.commit(false); + } catch (EBaseException e) { + } + getConfigEntriesFromMaster(request, response, context); + context.put("updateStatus", "success"); + return; + } + String pwd = HttpInput.getPassword(request, "__password"); + + String tokenn = ""; + String instanceRoot = ""; + + try { + tokenn = config.getString("preop.module.token"); + instanceRoot = config.getString("instanceRoot"); + } catch (Exception e) { + } + + if (tokenn.equals("Internal Key Storage Token")) { + byte b[] = new byte[1000000]; + FileInputStream fis = new FileInputStream(instanceRoot + "/alias/" + path); + while (fis.available() > 0) + fis.read(b); + fis.close(); + + ByteArrayInputStream bis = new ByteArrayInputStream(b); + StringBuffer reason = new StringBuffer(); + Password password = new Password(pwd.toCharArray()); + PFX pfx = null; + boolean verifypfx = false; + try { + pfx = (PFX) (new PFX.Template()).decode(bis); + verifypfx = pfx.verifyAuthSafes(password, reason); + } catch (Exception e) { + CMS.debug("RestoreKeyCertPanel update: Exception=" + e.toString()); + } + + if (verifypfx) { + CMS.debug("RestoreKeyCertPanel verify the PFX."); + AuthenticatedSafes safes = pfx.getAuthSafes(); + Vector<Vector<Object>> pkeyinfo_collection = new Vector<Vector<Object>>(); + Vector<Vector<Object>> cert_collection = new Vector<Vector<Object>>(); + for (int i = 0; i < safes.getSize(); i++) { + try { + SEQUENCE scontent = safes.getSafeContentsAt(null, i); + for (int j = 0; j < scontent.size(); j++) { + SafeBag bag = (SafeBag) scontent.elementAt(j); + OBJECT_IDENTIFIER oid = bag.getBagType(); + if (oid.equals(SafeBag.PKCS8_SHROUDED_KEY_BAG)) { + EncryptedPrivateKeyInfo privkeyinfo = + (EncryptedPrivateKeyInfo) bag.getInterpretedBagContent(); + PrivateKeyInfo pkeyinfo = privkeyinfo.decrypt(password, new PasswordConverter()); + Vector<Object> pkeyinfo_v = new Vector<Object>(); + pkeyinfo_v.addElement(pkeyinfo); + SET bagAttrs = bag.getBagAttributes(); + for (int k = 0; k < bagAttrs.size(); k++) { + Attribute attrs = (Attribute) bagAttrs.elementAt(k); + OBJECT_IDENTIFIER aoid = attrs.getType(); + if (aoid.equals(SafeBag.FRIENDLY_NAME)) { + SET val = attrs.getValues(); + ANY ss = (ANY) val.elementAt(0); + ByteArrayInputStream bbis = new ByteArrayInputStream(ss.getEncoded()); + BMPString sss = (BMPString) new BMPString.Template().decode(bbis); + String s = sss.toString(); + pkeyinfo_v.addElement(s); + } + } + pkeyinfo_collection.addElement(pkeyinfo_v); + } else if (oid.equals(SafeBag.CERT_BAG)) { + CertBag cbag = (CertBag) bag.getInterpretedBagContent(); + OCTET_STRING str = (OCTET_STRING) cbag.getInterpretedCert(); + byte[] x509cert = str.toByteArray(); + Vector<Object> cert_v = new Vector<Object>(); + cert_v.addElement(x509cert); + SET bagAttrs = bag.getBagAttributes(); + + if (bagAttrs != null) { + for (int k = 0; k < bagAttrs.size(); k++) { + Attribute attrs = (Attribute) bagAttrs.elementAt(k); + OBJECT_IDENTIFIER aoid = attrs.getType(); + if (aoid.equals(SafeBag.FRIENDLY_NAME)) { + SET val = attrs.getValues(); + ANY ss = (ANY) val.elementAt(0); + ByteArrayInputStream bbis = new ByteArrayInputStream(ss.getEncoded()); + BMPString sss = (BMPString) (new BMPString.Template()).decode(bbis); + String s = sss.toString(); + cert_v.addElement(s); + } + } + } + + cert_collection.addElement(cert_v); + } + } + } catch (Exception e) { + CMS.debug("RestoreKeyCertPanel update: Exception=" + e.toString()); + } + } + + importkeycert(pkeyinfo_collection, cert_collection); + } else { + context.put("updateStatus", "failure"); + throw new IOException("The pkcs12 file is not correct."); + } + } + + String subsystemtype = ""; + String cstype = ""; + try { + subsystemtype = config.getString("preop.subsystem.select", ""); + cstype = config.getString("cs.type", ""); + } catch (Exception e) { + } + cstype = toLowerCaseSubsystemType(cstype); + + if (subsystemtype.equals("clone")) { + CMS.debug("RestoreKeyCertPanel: this is the clone subsystem"); + boolean cloneReady = isCertdbCloned(request, context); + if (!cloneReady) { + CMS.debug("RestoreKeyCertPanel update: clone does not have all the certificates."); + context.put("errorString", "Make sure you have copied the certificate database over to the clone"); + context.put("updateStatus", "failure"); + throw new IOException("Clone is not ready"); + } + } + + config.putBoolean("preop.restorekeycert.done", true); + try { + config.commit(false); + } catch (EBaseException e) { + } + + getConfigEntriesFromMaster(request, response, context); + context.put("updateStatus", "success"); + } + + private void getConfigEntriesFromMaster(HttpServletRequest request, + HttpServletResponse response, Context context) throws IOException { + try { + IConfigStore config = CMS.getConfigStore(); + String cstype = ""; + try { + cstype = config.getString("cs.type", ""); + } catch (Exception e) { + } + cstype = toLowerCaseSubsystemType(cstype); + + String session_id = CMS.getConfigSDSessionId(); + String master_hostname = ""; + int master_port = -1; + int master_ee_port = -1; + try { + master_hostname = config.getString("preop.master.hostname", ""); + master_port = config.getInteger("preop.master.httpsadminport", -1); + master_ee_port = config.getInteger("preop.master.httpsport", -1); + + String content = ""; + if (cstype.equals("ca") || cstype.equals("kra")) { + content = "type=request&xmlOutput=true&sessionID=" + session_id; + CMS.debug("http content=" + content); + updateNumberRange(master_hostname, master_ee_port, true, content, "request", response); + + content = "type=serialNo&xmlOutput=true&sessionID=" + session_id; + updateNumberRange(master_hostname, master_ee_port, true, content, "serialNo", response); + + content = "type=replicaId&xmlOutput=true&sessionID=" + session_id; + updateNumberRange(master_hostname, master_ee_port, true, content, "replicaId", response); + } + + String list = ""; + try { + list = config.getString("preop.cert.list", ""); + } catch (Exception e) { + } + + StringBuffer c1 = new StringBuffer(); + StringBuffer s1 = new StringBuffer(); + StringTokenizer tok = new StringTokenizer(list, ","); + while (tok.hasMoreTokens()) { + String t1 = tok.nextToken(); + if (t1.equals("sslserver")) + continue; + c1.append(","); + c1.append("cloning."); + c1.append(t1); + c1.append(".nickname,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".dn,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".keytype,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".keyalgorithm,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".privkey.id,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".pubkey.exponent,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".pubkey.modulus,"); + c1.append("cloning."); + c1.append(t1); + c1.append(".pubkey.encoded"); + + if (s1.length() != 0) + s1.append(","); + + s1.append(cstype); + s1.append("."); + s1.append(t1); + } + + if (!cstype.equals("ca")) { + c1.append(",cloning.ca.hostname,cloning.ca.httpport,cloning.ca.httpsport,cloning.ca.list,cloning.ca.pkcs7,cloning.ca.type"); + } + + if (cstype.equals("ca")) { + /* get ca connector details */ + if (s1.length() != 0) + s1.append(","); + s1.append("ca.connector.KRA"); + } + + s1.append(",internaldb,internaldb.ldapauth,internaldb.ldapconn"); + + content = + "op=get&names=cloning.token,instanceId,internaldb.basedn,internaldb.ldapauth.password," + + "internaldb.replication.password" + c1.toString() + + "&substores=" + s1.toString() + + "&xmlOutput=true&sessionID=" + + session_id; + boolean success = updateConfigEntries(master_hostname, master_port, true, + "/" + cstype + "/admin/" + cstype + "/getConfigEntries", content, config, response); + if (!success) { + context.put("errorString", "Failed to get configuration entries from the master"); + throw new IOException("Failed to get configuration entries from the master"); + } + config.putString("preop.clone.configuration", "true"); + try { + config.commit(false); + } catch (Exception ee) { + } + } catch (IOException eee) { + throw eee; + } catch (Exception eee) { + CMS.debug("RestoreKeyCertPanel: update exception caught:" + eee.toString()); + } + + } catch (IOException ee) { + throw ee; + } catch (Exception ee) { + } + } + + private void deleteExistingCerts() { + IConfigStore cs = CMS.getConfigStore(); + try { + String list = cs.getString("preop.cert.list", ""); + StringTokenizer st = new StringTokenizer(list, ","); + while (st.hasMoreTokens()) { + String s = st.nextToken(); + if (s.equals("sslserver")) + continue; + String name = "preop.master." + s + ".nickname"; + String nickname = cs.getString(name, ""); + CryptoManager cm = CryptoManager.getInstance(); + X509Certificate xcert = null; + try { + xcert = cm.findCertByNickname(nickname); + } catch (Exception ee) { + CMS.debug("RestoreKeyCertPanel deleteExistingCerts: Exception=" + ee.toString()); + } + CryptoToken ct = cm.getInternalKeyStorageToken(); + CryptoStore store = ct.getCryptoStore(); + try { + store.deleteCert(xcert); + } catch (Exception ee) { + CMS.debug("RestoreKeyCertPanel deleteExistingCerts: Exception=" + ee.toString()); + } + } + } catch (Exception e) { + CMS.debug("RestoreKeyCertPanel deleteExistingCerts: Exception=" + e.toString()); + } + } + + private org.mozilla.jss.crypto.PrivateKey.Type getPrivateKeyType(PublicKey pubkey) { + CMS.debug("Key Algorithm '" + pubkey.getAlgorithm() + "'"); + if (pubkey.getAlgorithm().equals("EC")) { + return org.mozilla.jss.crypto.PrivateKey.Type.EC; + } + return org.mozilla.jss.crypto.PrivateKey.Type.RSA; + } + + private void importkeycert(Vector<Vector<Object>> pkeyinfo_collection, + Vector<Vector<Object>> cert_collection) throws IOException { + CryptoManager cm = null; + try { + cm = CryptoManager.getInstance(); + } catch (Exception e) { + } + + // delete all existing certificates first + deleteExistingCerts(); + + for (int i = 0; i < pkeyinfo_collection.size(); i++) { + try { + Vector<Object> pkeyinfo_v = pkeyinfo_collection.elementAt(i); + PrivateKeyInfo pkeyinfo = (PrivateKeyInfo) pkeyinfo_v.elementAt(0); + String nickname = (String) pkeyinfo_v.elementAt(1); + byte[] x509cert = getX509Cert(nickname, cert_collection); + X509Certificate cert = cm.importCACertPackage(x509cert); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + pkeyinfo.encode(bos); + byte[] pkey = bos.toByteArray(); + + PublicKey publickey = cert.getPublicKey(); + CryptoToken token = cm.getInternalKeyStorageToken(); + CryptoStore store = token.getCryptoStore(); + CMS.debug("RestoreKeyCertPanel deleteCert: this is pk11store"); + try { + store.deleteCert(cert); + } catch (Exception ee) { + CMS.debug("RestoreKeyCertPanel importKeyCert: Exception=" + ee.toString()); + } + + KeyGenerator kg = token.getKeyGenerator(KeyGenAlgorithm.DES3); + SymmetricKey sk = kg.generate(); + byte iv[] = { 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 }; + IVParameterSpec param = new IVParameterSpec(iv); + Cipher c = token.getCipherContext(EncryptionAlgorithm.DES3_CBC_PAD); + c.initEncrypt(sk, param); + byte[] encpkey = c.doFinal(pkey); + + KeyWrapper wrapper = token.getKeyWrapper(KeyWrapAlgorithm.DES3_CBC_PAD); + wrapper.initUnwrap(sk, param); + wrapper.unwrapPrivate(encpkey, getPrivateKeyType(publickey), publickey); + + } catch (Exception e) { + CMS.debug("RestoreKeyCertPanel importkeycert: Exception=" + e.toString()); + } + } + + for (int i = 0; i < cert_collection.size(); i++) { + try { + Vector<Object> cert_v = cert_collection.elementAt(i); + byte[] cert = (byte[]) cert_v.elementAt(0); + if (cert_v.size() > 1) { + String name = (String) cert_v.elementAt(1); + // we need to delete the trusted CA certificate if it is + // the same as the ca signing certificate + if (isCASigningCert(name)) { + X509Certificate certchain = getX509CertFromToken(cert); + if (certchain != null) { + CryptoToken token = cm.getInternalKeyStorageToken(); + CryptoStore store = token.getCryptoStore(); + CMS.debug("RestoreKeyCertPanel deleteCert: this is pk11store"); + if (store instanceof PK11Store) { + try { + PK11Store pk11store = (PK11Store) store; + pk11store.deleteCertOnly(certchain); + } catch (Exception ee) { + CMS.debug("RestoreKeyCertPanel importKeyCert: Exception=" + ee.toString()); + } + } + } + } + + X509Certificate xcert = cm.importUserCACertPackage(cert, name); + if (name.startsWith("caSigningCert")) { + // we need to change the trust attribute to CT + InternalCertificate icert = (InternalCertificate) xcert; + icert.setSSLTrust(InternalCertificate.TRUSTED_CA + | InternalCertificate.TRUSTED_CLIENT_CA + | InternalCertificate.VALID_CA); + } else if (name.startsWith("auditSigningCert")) { + InternalCertificate icert = (InternalCertificate) xcert; + icert.setObjectSigningTrust(InternalCertificate.USER + | InternalCertificate.VALID_PEER | InternalCertificate.TRUSTED_PEER); + } + } else + cm.importCACertPackage(cert); + } catch (Exception e) { + CMS.debug("RestoreKeyCertPanel importkeycert: Exception=" + e.toString()); + } + } + } + + private boolean isCASigningCert(String name) { + String n = "preop.master.signing.nickname"; + IConfigStore cs = CMS.getConfigStore(); + try { + String nickname = cs.getString(n); + if (nickname.equals(name)) + return true; + } catch (Exception e) { + return false; + } + + return false; + } + + private X509Certificate getX509CertFromToken(byte[] cert) + throws IOException { + try { + X509CertImpl impl = new X509CertImpl(cert); + String issuer_impl = impl.getIssuerDN().toString(); + BigInteger serial_impl = impl.getSerialNumber(); + CryptoManager cm = CryptoManager.getInstance(); + X509Certificate[] permcerts = cm.getPermCerts(); + for (int i = 0; i < permcerts.length; i++) { + String issuer_p = permcerts[i].getSubjectDN().toString(); + BigInteger serial_p = permcerts[i].getSerialNumber(); + if (issuer_p.equals(issuer_impl) && serial_p.compareTo(serial_impl) == 0) { + return permcerts[i]; + } + } + } catch (Exception e) { + CMS.debug("RestoreKeyCertPanel getX509CertFromToken: Exception=" + e.toString()); + } + + return null; + } + + private byte[] getX509Cert(String nickname, Vector<Vector<Object>> cert_collection) + throws IOException { + for (int i = 0; i < cert_collection.size(); i++) { + Vector<Object> v = cert_collection.elementAt(i); + byte[] b = (byte[]) v.elementAt(0); + X509CertImpl impl = null; + try { + impl = new X509CertImpl(b); + } catch (Exception e) { + CMS.debug("RestoreKeyCertPanel getX509Cert: Exception=" + e.toString()); + throw new IOException(e.toString()); + } + Principal subjectdn = impl.getSubjectDN(); + if (LDAPDN.equals(subjectdn.toString(), nickname)) + return b; + } + + return null; + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Import Keys and Certificates"); + context.put("password", ""); + context.put("path", ""); + context.put("panel", "admin/console/config/restorekeycertpanel.vm"); + } + + private boolean isCertdbCloned(HttpServletRequest request, + Context context) { + IConfigStore config = CMS.getConfigStore(); + String certList = ""; + try { + CryptoManager cm = CryptoManager.getInstance(); + certList = config.getString("preop.cert.list"); + StringTokenizer st = new StringTokenizer(certList, ","); + while (st.hasMoreTokens()) { + String token = st.nextToken(); + if (token.equals("sslserver")) + continue; + String tokenname = config.getString("preop.module.token", ""); + cm.getTokenByName(tokenname); // throw exception if token doesn't exist + String name1 = "preop.master." + token + ".nickname"; + String nickname = config.getString(name1, ""); + if (!tokenname.equals("Internal Key Storage Token") && + !tokenname.equals("internal")) + nickname = tokenname + ":" + nickname; + + CMS.debug("RestoreKeyCertPanel isCertdbCloned: " + nickname); + X509Certificate cert = cm.findCertByNickname(nickname); + if (cert == null) + return false; + } + } catch (Exception e) { + context.put("errorString", "Check your CS.cfg for cloning"); + return false; + } + + return true; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java b/base/common/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java new file mode 100644 index 000000000..0c066268d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java @@ -0,0 +1,144 @@ +// --- 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.csadmin; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class SavePKCS12Panel extends WizardPanelBase { + + public SavePKCS12Panel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Save Keys and Certificates"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Save Keys and Certificates"); + setId(id); + } + + public void cleanUp() throws IOException { + } + + public boolean shouldSkip() { + IConfigStore cs = CMS.getConfigStore(); + + try { + boolean enable = cs.getBoolean("preop.backupkeys.enable", false); + if (!enable) + return true; + } catch (Exception e) { + } + + return false; + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.backupkeycert.done", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + return set; + } + + public boolean isSubPanel() { + return true; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Save Keys and Certificates"); + IConfigStore config = CMS.getConfigStore(); + String subsystemtype = ""; + try { + subsystemtype = config.getString("cs.type", ""); + } catch (Exception e) { + } + + subsystemtype = toLowerCaseSubsystemType(subsystemtype); + + context.put("panel", "admin/console/config/savepkcs12panel.vm"); + context.put("subsystemtype", subsystemtype); + context.put("errorString", ""); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + context.put("title", "Save Keys and Certificates"); + context.put("panel", "admin/console/config/savepkcs12panel.vm"); + context.put("updateStatus", "success"); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Save Keys and Certificates"); + context.put("panel", "admin/console/config/savepkcs12panel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java new file mode 100644 index 000000000..42165b08f --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java @@ -0,0 +1,87 @@ +// --- 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.csadmin; + +import java.net.URL; +import java.net.URLDecoder; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; + +public class SecurityDomainLogin extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = -1616344299101179396L; + + public boolean authenticate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + return true; + } + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + Template template = null; + + try { + String url = request.getParameter("url"); + url = URLDecoder.decode(url, "UTF-8"); + URL u = null; + if (url != null) { + u = new URL(url); + } + int index = url.indexOf("subsystem="); + String subsystem = ""; + if (index > 0) { + subsystem = url.substring(index + 10); + int index1 = subsystem.indexOf("&"); + if (index1 > 0) + subsystem = subsystem.substring(0, index1); + } + context.put("sd_uid", ""); + context.put("sd_pwd", ""); + context.put("url", url); + context.put("host", u.getHost()); + context.put("sdhost", CMS.getEESSLHost()); + if (subsystem.equals("KRA")) { + subsystem = "DRM"; + } + context.put("subsystem", subsystem); + // The "securitydomain.name" property ONLY resides in the "CS.cfg" + // associated with the CS subsystem hosting the security domain. + IConfigStore cs = CMS.getConfigStore(); + String sdname = cs.getString("securitydomain.name", ""); + context.put("name", sdname); + template = Velocity.getTemplate("admin/console/config/securitydomainloginpanel.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java new file mode 100644 index 000000000..f3a4169e8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java @@ -0,0 +1,500 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class SecurityDomainPanel extends WizardPanelBase { + + public SecurityDomainPanel() { + } + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + setPanelNo(panelno); + setName("Security Domain"); + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Security Domain"); + setId(id); + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.securitydomain.select", ""); + cs.putString("securitydomain.select", ""); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + String s = cs.getString("preop.securitydomain.select", ""); + if (s == null || s.equals("")) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Security Domain"); + IConfigStore config = CMS.getConfigStore(); + String errorString = ""; + String default_admin_url = ""; + String name = ""; + String systemdService = ""; + + try { + default_admin_url = config.getString("preop.securitydomain.admin_url", ""); + name = config.getString("preop.securitydomain.name", ""); + systemdService = config.getString("pkicreate.systemd.servicename", ""); + } catch (Exception e) { + CMS.debug(e.toString()); + } + if (isPanelDone()) { + try { + String s = config.getString("preop.securitydomain.select"); + + if (s.equals("new")) { + context.put("check_newdomain", "checked"); + context.put("check_existingdomain", ""); + } else if (s.equals("existing")) { + context.put("check_newdomain", ""); + context.put("check_existingdomain", "checked"); + } + } catch (Exception e) { + CMS.debug(e.toString()); + } + } else { + context.put("check_newdomain", "checked"); + context.put("check_existingdomain", ""); + } + + try { + context.put("cstype", config.getString("cs.type")); + context.put("wizardname", config.getString("preop.wizard.name")); + context.put("panelname", "Security Domain Configuration"); + context.put("systemname", config.getString("preop.system.name")); + context.put("machineName", config.getString("machineName")); + context.put("http_ee_port", CMS.getEENonSSLPort()); + context.put("https_agent_port", CMS.getAgentPort()); + context.put("https_ee_port", CMS.getEESSLPort()); + context.put("https_admin_port", CMS.getAdminPort()); + context.put("sdomainAdminURL", default_admin_url); + } catch (EBaseException e) { + } + + context.put("panel", "admin/console/config/securitydomainpanel.vm"); + context.put("errorString", errorString); + + // from default_admin_url, find hostname, if fully qualified, get + // network domain name and generate default security domain name + if (name.equals("") && (default_admin_url != null)) { + try { + URL u = new URL(default_admin_url); + + String hostname = u.getHost(); + StringTokenizer st = new StringTokenizer(hostname, "."); + boolean first = true; + int numTokens = st.countTokens(); + int count = 0; + String defaultDomain = ""; + StringBuffer sb = new StringBuffer(); + while (st.hasMoreTokens()) { + count++; + String n = st.nextToken(); + if (first) { //skip the hostname + first = false; + continue; + } + if (count == numTokens) // skip the last element (e.g. com) + continue; + sb.append((defaultDomain.length() == 0) ? "" : " "); + sb.append(capitalize(n)); + } + defaultDomain = sb.toString() + " " + "Domain"; + name = defaultDomain; + CMS.debug("SecurityDomainPanel: defaultDomain generated:" + name); + } catch (MalformedURLException e) { + errorString = "Malformed URL"; + // not being able to come up with default domain name is ok + } + } + context.put("sdomainName", name); + + if (default_admin_url != null) { + String r = null; + + try { + // check to see if "default" security domain exists + // on local machine + URL u = new URL(default_admin_url); + + String hostname = u.getHost(); + int port = u.getPort(); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + r = pingCS(hostname, port, true, certApprovalCallback); + } catch (Exception e) { + CMS.debug("SecurityDomainPanel: exception caught: " + + e.toString()); + } + + if (r != null) { + // "default" security domain exists on local machine; + // fill "sdomainURL" in with "default" security domain + // as an initial "guess" + CMS.debug("SecurityDomainPanel: pingCS returns: " + r); + context.put("sdomainURL", default_admin_url); + } else { + // "default" security domain does NOT exist on local machine; + // leave "sdomainURL" blank + CMS.debug("SecurityDomainPanel: pingCS no successful response"); + context.put("sdomainURL", ""); + } + } + + // Information for "existing" Security Domain CAs + String initDaemon = "pki-cad"; + String instanceId = "<security_domain_instance_name>"; + String os = System.getProperty("os.name"); + if (os.equalsIgnoreCase("Linux")) { + if (!systemdService.equals("")) { + context.put("initCommand", "/usr/bin/pkicontrol"); + context.put("instanceId", "ca " + systemdService); + } else { + context.put("initCommand", "/sbin/service " + initDaemon); + context.put("instanceId", instanceId); + } + } else { + /* default case: e. g. - ( os.equalsIgnoreCase( "SunOS" ) */ + context.put("initCommand", "/etc/init.d/" + initDaemon); + context.put("instanceId", instanceId); + } + } + + public static String capitalize(String s) { + if (s.length() == 0) { + return s; + } else { + return s.substring(0, 1).toUpperCase() + s.substring(1); + } + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + + String select = HttpInput.getID(request, "choice"); + if (select.equals("newdomain")) { + String name = HttpInput.getSecurityDomainName(request, "sdomainName"); + if (name == null || name.equals("")) { + initParams(request, context); + context.put("updateStatus", "validate-failure"); + throw new IOException("Missing name value for the security domain"); + } + } else if (select.equals("existingdomain")) { + CMS.debug("SecurityDomainPanel: validating " + + "SSL Admin HTTPS . . ."); + String admin_url = HttpInput.getURL(request, "sdomainURL"); + if (admin_url == null || admin_url.equals("")) { + initParams(request, context); + context.put("updateStatus", "validate-failure"); + throw new IOException("Missing SSL Admin HTTPS url value " + + "for the security domain"); + } else { + String r = null; + + try { + URL u = new URL(admin_url); + + String hostname = u.getHost(); + int admin_port = u.getPort(); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + r = pingCS(hostname, admin_port, true, + certApprovalCallback); + } catch (Exception e) { + CMS.debug("SecurityDomainPanel: exception caught: " + + e.toString()); + context.put("updateStatus", "validate-failure"); + throw new IOException("Illegal SSL Admin HTTPS url value " + + "for the security domain"); + } + + if (r != null) { + CMS.debug("SecurityDomainPanel: pingAdminCS returns: " + + r); + context.put("sdomainURL", admin_url); + } else { + CMS.debug("SecurityDomainPanel: pingAdminCS " + + "no successful response for SSL Admin HTTPS"); + context.put("sdomainURL", ""); + } + } + } + } + + public void initParams(HttpServletRequest request, Context context) + throws IOException { + IConfigStore config = CMS.getConfigStore(); + try { + context.put("cstype", config.getString("cs.type")); + } catch (Exception e) { + } + + String select = request.getParameter("choice"); + if (select.equals("newdomain")) { + context.put("check_newdomain", "checked"); + context.put("check_existingdomain", ""); + } else if (select.equals("existingdomain")) { + context.put("check_newdomain", ""); + context.put("check_existingdomain", "checked"); + } + + String name = request.getParameter("sdomainName"); + if (name == null) + name = ""; + context.put("sdomainName", name); + + String admin_url = request.getParameter("sdomainURL"); + if (admin_url == null) + admin_url = ""; + context.put("sdomainURL", admin_url); + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + String errorString = ""; + String select = HttpInput.getID(request, "choice"); + + if (select == null) { + CMS.debug("SecurityDomainPanel: choice not found"); + context.put("updateStatus", "failure"); + throw new IOException("choice not found"); + } + IConfigStore config = CMS.getConfigStore(); + + if (select.equals("newdomain")) { + config.putString("preop.securitydomain.select", "new"); + config.putString("securitydomain.select", "new"); + config.putString("preop.securitydomain.name", + HttpInput.getDomainName(request, "sdomainName")); + config.putString("securitydomain.name", + HttpInput.getDomainName(request, "sdomainName")); + config.putString("securitydomain.host", + CMS.getEENonSSLHost()); + config.putString("securitydomain.httpport", + CMS.getEENonSSLPort()); + config.putString("securitydomain.httpsagentport", + CMS.getAgentPort()); + config.putString("securitydomain.httpseeport", + CMS.getEESSLPort()); + config.putString("securitydomain.httpsadminport", + CMS.getAdminPort()); + + // make sure the subsystem certificate is issued by the security + // domain + config.putString("preop.cert.subsystem.type", "local"); + config.putString("preop.cert.subsystem.profile", "subsystemCert.profile"); + + try { + config.commit(false); + } catch (EBaseException e) { + } + + } else if (select.equals("existingdomain")) { + config.putString("preop.securitydomain.select", "existing"); + config.putString("securitydomain.select", "existing"); + + // make sure the subsystem certificate is issued by the security + // domain + config.putString("preop.cert.subsystem.type", "remote"); + config.putString("preop.cert.subsystem.profile", "caInternalAuthSubsystemCert"); + + String admin_url = HttpInput.getURL(request, "sdomainURL"); + String hostname = ""; + int admin_port = -1; + + if (admin_url != null) { + try { + URL admin_u = new URL(admin_url); + + hostname = admin_u.getHost(); + admin_port = admin_u.getPort(); + } catch (MalformedURLException e) { + errorString = "Malformed SSL Admin HTTPS URL"; + context.put("updateStatus", "failure"); + throw new IOException(errorString); + } + + context.put("sdomainURL", admin_url); + config.putString("securitydomain.host", hostname); + config.putInteger("securitydomain.httpsadminport", + admin_port); + } + + try { + config.commit(false); + } catch (EBaseException e) { + } + + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + updateCertChain(config, "securitydomain", hostname, admin_port, + true, context, certApprovalCallback); + } else { + CMS.debug("SecurityDomainPanel: invalid choice " + select); + errorString = "Invalid choice"; + context.put("updateStatus", "failure"); + throw new IOException("invalid choice " + select); + } + + try { + config.commit(false); + } catch (EBaseException e) { + } + + try { + context.put("cstype", config.getString("cs.type")); + context.put("wizardname", config.getString("preop.wizard.name")); + context.put("panelname", "Security Domain Configuration"); + context.put("systemname", config.getString("preop.system.name")); + } catch (EBaseException e) { + } + + context.put("errorString", errorString); + context.put("updateStatus", "success"); + } + + /** + * If validate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + IConfigStore config = CMS.getConfigStore(); + String default_admin_url = ""; + try { + initParams(request, context); + } catch (IOException e) { + } + + try { + default_admin_url = config.getString("preop.securitydomain.admin_url", ""); + } catch (Exception e) { + } + + if (default_admin_url != null) { + String r = null; + + try { + // check to see if "default" security domain exists + // on local machine + URL u = new URL(default_admin_url); + + String hostname = u.getHost(); + int port = u.getPort(); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + r = pingCS(hostname, port, true, certApprovalCallback); + } catch (Exception e) { + } + + if (r != null) { + // "default" security domain exists on local machine; + // refill "sdomainURL" in with "default" security domain + // as an initial "guess" + context.put("sdomainURL", default_admin_url); + } else { + // "default" security domain does NOT exist on local machine; + // leave "sdomainURL" blank + context.put("sdomainURL", ""); + } + } + + try { + context.put("machineName", config.getString("machineName")); + context.put("http_ee_port", CMS.getEENonSSLPort()); + context.put("https_agent_port", CMS.getAgentPort()); + context.put("https_ee_port", CMS.getEESSLPort()); + context.put("https_admin_port", CMS.getAdminPort()); + context.put("sdomainAdminURL", + config.getString("preop.securitydomain.admin_url")); + } catch (EBaseException e) { + } + + // Information for "existing" Security Domain CAs + String initDaemon = "pki-cad"; + String instanceId = "<security_domain_instance_name>"; + String os = System.getProperty("os.name"); + if (os.equalsIgnoreCase("Linux")) { + context.put("initCommand", "/sbin/service " + initDaemon); + context.put("instanceId", instanceId); + } else { + /* default case: e. g. - ( os.equalsIgnoreCase( "SunOS" ) */ + context.put("initCommand", "/etc/init.d/" + initDaemon); + context.put("instanceId", instanceId); + } + + context.put("title", "Security Domain"); + context.put("panel", "admin/console/config/securitydomainpanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainSessionTable.java b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainSessionTable.java new file mode 100644 index 000000000..d15ca5ad3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainSessionTable.java @@ -0,0 +1,105 @@ +// --- 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.csadmin; + +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import com.netscape.certsrv.base.ISecurityDomainSessionTable; + +/** + * This object stores the values for IP, uid and group based on the cookie id. + */ +public class SecurityDomainSessionTable + implements ISecurityDomainSessionTable { + + private Hashtable<String, Vector<Comparable<?>>> m_sessions; + private long m_timeToLive; + + public SecurityDomainSessionTable(long timeToLive) { + m_sessions = new Hashtable<String, Vector<Comparable<?>>>(); + m_timeToLive = timeToLive; + } + + public int addEntry(String sessionId, String ip, + String uid, String group) { + Vector<Comparable<?>> v = new Vector<Comparable<?>>(); + v.addElement(ip); + v.addElement(uid); + v.addElement(group); + Date d = new Date(); + long t = d.getTime(); + v.addElement(Long.valueOf(t)); + m_sessions.put(sessionId, v); + return SUCCESS; + } + + public int removeEntry(String sessionId) { + m_sessions.remove(sessionId); + return SUCCESS; + } + + public boolean isSessionIdExist(String sessionId) { + return m_sessions.containsKey(sessionId); + } + + public Enumeration<String> getSessionIds() { + return m_sessions.keys(); + } + + public String getIP(String sessionId) { + Vector<Comparable<?>> v = m_sessions.get(sessionId); + if (v != null) + return (String) v.elementAt(0); + return null; + } + + public String getUID(String sessionId) { + Vector<Comparable<?>> v = m_sessions.get(sessionId); + if (v != null) + return (String) v.elementAt(1); + return null; + } + + public String getGroup(String sessionId) { + Vector<Comparable<?>> v = m_sessions.get(sessionId); + if (v != null) + return (String) v.elementAt(2); + return null; + } + + public long getBeginTime(String sessionId) { + Vector<Comparable<?>> v = m_sessions.get(sessionId); + if (v != null) { + Long n = (Long) v.elementAt(3); + if (n != null) + return n.longValue(); + } + return -1; + } + + public long getTimeToLive() { + return m_timeToLive; + } + + public int getSize() { + return m_sessions.size(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SessionTimer.java b/base/common/src/com/netscape/cms/servlet/csadmin/SessionTimer.java new file mode 100644 index 000000000..2d8a188af --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/SessionTimer.java @@ -0,0 +1,68 @@ +// --- 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.csadmin; + +import java.util.Date; +import java.util.Enumeration; +import java.util.TimerTask; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.ISecurityDomainSessionTable; +import com.netscape.certsrv.logging.ILogger; + +public class SessionTimer extends TimerTask { + private ISecurityDomainSessionTable m_sessiontable = null; + private ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + private final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE = + "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1"; + + public SessionTimer(ISecurityDomainSessionTable table) { + super(); + m_sessiontable = table; + } + + public void run() { + Enumeration<String> keys = m_sessiontable.getSessionIds(); + while (keys.hasMoreElements()) { + String sessionId = keys.nextElement(); + long beginTime = m_sessiontable.getBeginTime(sessionId); + Date nowDate = new Date(); + long nowTime = nowDate.getTime(); + long timeToLive = m_sessiontable.getTimeToLive(); + if ((nowTime - beginTime) > timeToLive) { + m_sessiontable.removeEntry(sessionId); + CMS.debug("SessionTimer run: successfully remove the session id entry from the table."); + + // audit message + String auditParams = "operation;;expire_token+token;;" + sessionId; + String auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE, + "system", + ILogger.SUCCESS, + auditParams); + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + auditMessage); + + } + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SizePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/SizePanel.java new file mode 100644 index 000000000..678145a92 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/SizePanel.java @@ -0,0 +1,669 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.security.KeyPair; +import java.security.NoSuchAlgorithmException; +import java.security.interfaces.RSAPublicKey; +import java.util.Enumeration; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.NoSuchTokenException; +import org.mozilla.jss.crypto.TokenException; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.Descriptor; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.certsrv.util.HttpInput; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; + +public class SizePanel extends WizardPanelBase { + private Vector<Cert> mCerts = null; + private WizardServlet mServlet = null; + + private String default_ecc_curve_name; + private String default_rsa_key_size; + private boolean mShowSigning = false; + + public SizePanel() { + } + + /** + * Initializes this panel. + */ + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Key Pairs"); + setId(id); + mServlet = servlet; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + Descriptor choiceDesc = + new Descriptor( + IDescriptor.CHOICE, + "default,custom", + null, /* no default parameter */ + "If 'default', the key size will be configured automatically. If 'custom', the key size will be set to the value of the parameter 'custom_size'."); + + set.add("choice", choiceDesc); + + Descriptor customSizeDesc = new Descriptor(IDescriptor.STRING, null, /* no constraint */ + null, /* no default parameter */ + "Custom Key Size"); + + set.add("custom_size", customSizeDesc); + + return set; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + /* clean up if necessary*/ + try { + @SuppressWarnings("unused") + boolean done = cs.getBoolean("preop.SizePanel.done"); // check for errors + cs.putBoolean("preop.SizePanel.done", false); + cs.commit(false); + } catch (Exception e) { + } + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + boolean s = cs.getBoolean("preop.SizePanel.done", false); + if (s != true) { + return false; + } else { + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("SizePanel: display()"); + try { + initParams(request, context); + } catch (IOException e) { + } + + context.put("firsttime", "false"); + String errorString = ""; + mCerts = new Vector<Cert>(); + + IConfigStore config = CMS.getConfigStore(); + try { + @SuppressWarnings("unused") + boolean done = config.getBoolean("preop.SizePanel.done"); // check whether it's first time + } catch (Exception e) { + context.put("firsttime", "true"); + } + + try { + default_ecc_curve_name = config.getString("keys.ecc.curve.default", "nistp256"); + } catch (Exception e) { + } + + try { + default_rsa_key_size = config.getString("keys.rsa.keysize.default", "2048"); + } catch (Exception e) { + } + + try { + // same token for now + String token = config.getString(PRE_CONF_CA_TOKEN); + String certTags = config.getString("preop.cert.list"); + String rsaCertTags = config.getString("preop.cert.rsalist", ""); + context.put("rsaTags", rsaCertTags); + StringTokenizer st = new StringTokenizer(certTags, ","); + mShowSigning = false; + + while (st.hasMoreTokens()) { + String certTag = st.nextToken(); + String nn = config.getString( + PCERT_PREFIX + certTag + ".nickname"); + Cert c = new Cert(token, nn, certTag); + + String s = config.getString( + PCERT_PREFIX + certTag + ".keysize.select", "default"); + + if (s.equals("default")) { + c.setKeyOption("default"); + } + if (s.equals("custom")) { + c.setKeyOption("custom"); + } + + s = config.getString( + PCERT_PREFIX + certTag + ".keysize.custom_size", + default_rsa_key_size); + c.setCustomKeysize(s); + + s = config.getString( + PCERT_PREFIX + certTag + ".curvename.custom_name", + default_ecc_curve_name); + c.setCustomCurvename(s); + + boolean signingRequired = config.getBoolean( + PCERT_PREFIX + certTag + ".signing.required", + false); + c.setSigningRequired(signingRequired); + if (signingRequired) + mShowSigning = true; + + String userfriendlyname = config.getString( + PCERT_PREFIX + certTag + ".userfriendlyname"); + c.setUserFriendlyName(userfriendlyname); + boolean enable = config.getBoolean(PCERT_PREFIX + certTag + ".enable", true); + c.setEnable(enable); + mCerts.addElement(c); + }// while + } catch (Exception e) { + CMS.debug("SizePanel: display() " + e.toString()); + } + CMS.debug("SizePanel: display() 1"); + + context.put("show_signing", mShowSigning ? "true" : "false"); + context.put("certs", mCerts); + context.put("errorString", errorString); + context.put("default_keysize", default_rsa_key_size); + context.put("default_ecc_curvename", default_ecc_curve_name); + context.put("panel", "admin/console/config/sizepanel.vm"); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException, NumberFormatException { + CMS.debug("SizePanel: update()"); + boolean hasErr = false; + IConfigStore config = CMS.getConfigStore(); + String select1 = ""; + String val1 = null; + boolean hasChanged = false; + try { + select1 = config.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + context.put("firsttime", "false"); + try { + @SuppressWarnings("unused") + boolean done = config.getBoolean("preop.SizePanel.done"); // check whether it's first time + } catch (Exception e) { + context.put("firsttime", "true"); + if (select1.equals("clone")) { + // preset the sslserver dn for cloning case + try { + String val = config.getString("preop.cert.sslserver.dn", ""); + config.putString("preop.cert.sslserver.dn", val + ",o=clone"); + } catch (Exception ee) { + } + } + } + + String token = ""; + try { + token = config.getString(PRE_CONF_CA_TOKEN, ""); + Enumeration<Cert> c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = c.nextElement(); + String ct = cert.getCertTag(); + boolean enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true); + if (!enable) + continue; + + String keytype = HttpInput.getKeyType(request, ct + "_keytype"); // rsa or ecc + + String keyalgorithm = HttpInput.getString(request, ct + "_keyalgorithm"); + if (keyalgorithm == null) { + if (keytype != null && keytype.equals("ecc")) { + keyalgorithm = "SHA256withEC"; + } else { + keyalgorithm = "SHA256withRSA"; + } + } + + String signingalgorithm = HttpInput.getString(request, ct + "_signingalgorithm"); + if (signingalgorithm == null) { + signingalgorithm = keyalgorithm; + } + + String select = HttpInput.getID(request, ct + "_choice"); + + if (select == null) { + CMS.debug("SizePanel: " + ct + "_choice not found"); + throw new IOException( + "SizePanel: " + ct + "_choice not found"); + } + CMS.debug( + "SizePanel: update() keysize choice selected:" + select); + String oldkeysize = + config.getString(PCERT_PREFIX + ct + ".keysize.size", ""); + String oldkeytype = + config.getString(PCERT_PREFIX + ct + ".keytype", ""); + String oldkeyalgorithm = + config.getString(PCERT_PREFIX + ct + ".keyalgorithm", ""); + String oldsigningalgorithm = + config.getString(PCERT_PREFIX + ct + ".signingalgorithm", ""); + String oldcurvename = + config.getString(PCERT_PREFIX + ct + ".curvename.name", ""); + + if (select.equals("default")) { + // XXXrenaming these...keep for now just in case + config.putString("preop.keysize.select", "default"); + if (keytype != null && keytype.equals("ecc")) { + config.putString("preop.curvename.custom_name", + default_ecc_curve_name); + config.putString("preop.curvename.name", default_ecc_curve_name); + } else { + config.putString("preop.keysize.custom_size", + default_rsa_key_size); + config.putString("preop.keysize.size", default_rsa_key_size); + } + + config.putString(PCERT_PREFIX + ct + ".keytype", keytype); + config.putString(PCERT_PREFIX + ct + ".keyalgorithm", keyalgorithm); + config.putString(PCERT_PREFIX + ct + ".signingalgorithm", signingalgorithm); + config.putString(PCERT_PREFIX + ct + ".keysize.select", + "default"); + + if (keytype != null && keytype.equals("ecc")) { + config.putString(PCERT_PREFIX + ct + + ".curvename.custom_name", + default_ecc_curve_name); + config.putString(PCERT_PREFIX + ct + ".curvename.name", + default_ecc_curve_name); + } else { + config.putString(PCERT_PREFIX + ct + + ".keysize.custom_size", + default_rsa_key_size); + config.putString(PCERT_PREFIX + ct + ".keysize.size", + default_rsa_key_size); + } + } else if (select.equals("custom")) { + // XXXrenaming these...keep for now just in case + config.putString("preop.keysize.select", "custom"); + if (keytype != null && keytype.equals("ecc")) { + config.putString("preop.curvename.name", + HttpInput.getString(request, ct + "_custom_curvename")); + config.putString("preop.curvename.custom_name", + HttpInput.getString(request, ct + "_custom_curvename")); + } else { + config.putString("preop.keysize.size", + HttpInput.getKeySize(request, ct + "_custom_size", keytype)); + config.putString("preop.keysize.custom_size", + HttpInput.getKeySize(request, ct + "_custom_size", keytype)); + } + + config.putString(PCERT_PREFIX + ct + ".keytype", keytype); + config.putString(PCERT_PREFIX + ct + ".keyalgorithm", keyalgorithm); + config.putString(PCERT_PREFIX + ct + ".signingalgorithm", signingalgorithm); + config.putString(PCERT_PREFIX + ct + ".keysize.select", + "custom"); + + if (keytype != null && keytype.equals("ecc")) { + config.putString(PCERT_PREFIX + ct + ".curvename.custom_name", + HttpInput.getString(request, ct + "_custom_curvename")); + config.putString(PCERT_PREFIX + ct + ".curvename.name", + HttpInput.getString(request, ct + "_custom_curvename")); + } else { + config.putString(PCERT_PREFIX + ct + ".keysize.custom_size", + HttpInput.getKeySize(request, ct + "_custom_size")); + config.putString(PCERT_PREFIX + ct + ".keysize.size", + HttpInput.getKeySize(request, ct + "_custom_size")); + } + } else { + CMS.debug("SizePanel: invalid choice " + select); + throw new IOException("invalid choice " + select); + } + + String newkeysize = + config.getString(PCERT_PREFIX + ct + ".keysize.size", ""); + String newkeytype = + config.getString(PCERT_PREFIX + ct + ".keytype", ""); + String newkeyalgorithm = + config.getString(PCERT_PREFIX + ct + ".keyalgorithm", ""); + String newsigningalgorithm = + config.getString(PCERT_PREFIX + ct + ".signingalgorithm", ""); + String newcurvename = + config.getString(PCERT_PREFIX + ct + ".curvename.name", ""); + + if (!oldkeysize.equals(newkeysize) || + !oldkeytype.equals(newkeytype) || + !oldkeyalgorithm.equals(newkeyalgorithm) || + !oldsigningalgorithm.equals(newsigningalgorithm) || + !oldcurvename.equals(newcurvename)) + hasChanged = true; + }// while + + try { + config.commit(false); + } catch (EBaseException e) { + CMS.debug("SizePanel: update() Exception caught at config commit: " + e.toString()); + } + + val1 = HttpInput.getID(request, "generateKeyPair"); + + if (hasChanged || (val1 != null && !val1.equals(""))) { + mServlet.cleanUpFromPanel(mServlet.getPanelNo(request)); + } else if (isPanelDone()) { + context.put("updateStatus", "success"); + return; + } + } catch (IOException e) { + CMS.debug("SizePanel: update() IOException caught: " + e.toString()); + context.put("updateStatus", "failure"); + throw e; + } catch (NumberFormatException e) { + CMS.debug("SizePanel: update() NumberFormatException caught: " + e.toString()); + context.put("updateStatus", "failure"); + throw e; + } catch (Exception e) { + CMS.debug("SizePanel: update() Exception caught: " + e.toString()); + } + + // generate key pair + Enumeration<Cert> c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = c.nextElement(); + String ct = cert.getCertTag(); + String friendlyName = ct; + boolean enable = true; + try { + enable = config.getBoolean(PCERT_PREFIX + ct + ".enable", true); + friendlyName = config.getString(PCERT_PREFIX + ct + ".userfriendlyname", ct); + } catch (Exception e) { + } + + if (!enable) + continue; + + try { + String keytype = config.getString(PCERT_PREFIX + ct + ".keytype"); + + if (keytype.equals("rsa")) { + int keysize = config.getInteger( + PCERT_PREFIX + ct + ".keysize.size"); + + createRSAKeyPair(token, keysize, config, ct); + } else { + String curveName = config.getString( + PCERT_PREFIX + ct + ".curvename.name", default_ecc_curve_name); + createECCKeyPair(token, curveName, config, ct); + } + config.commit(false); + } catch (Exception e) { + CMS.debug(e); + CMS.debug("SizePanel: key generation failure: " + e.toString()); + context.put("updateStatus", "failure"); + throw new IOException("key generation failure for the certificate: " + friendlyName + + ". See the logs for details."); + } + } // while + + if (hasErr == false) { + config.putBoolean("preop.SizePanel.done", true); + try { + config.commit(false); + } catch (EBaseException e) { + CMS.debug( + "SizePanel: update() Exception caught at config commit: " + + e.toString()); + } + } + CMS.debug("SizePanel: update() done"); + context.put("updateStatus", "success"); + + } + + public void createECCKeyPair(String token, String curveName, IConfigStore config, String ct) + throws NoSuchAlgorithmException, NoSuchTokenException, TokenException, + CryptoManager.NotInitializedException { + CMS.debug("Generating ECC key pair with curvename=" + curveName + + ", token=" + token); + KeyPair pair = null; + /* + * default ssl server cert to ECDHE unless stated otherwise + * note: IE only supports "ECDHE", but "ECDH" is more efficient + * + * for "ECDHE", server.xml should have the following for ciphers: + * +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + * -TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * + * for "ECDH", server.xml should have the following for ciphers: + * -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + * +TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + */ + String sslType = "ECDHE"; + try { + sslType = config.getString(PCERT_PREFIX + ct + "ec.type", "ECDHE"); + } catch (Exception e) { + CMS.debug("SizePanel: createECCKeyPair() Exception caught at config.getString for ec type"); + } + + // ECDHE needs "SIGN" but no "DERIVE" + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage usages_mask[] = { + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.DERIVE + }; + + // ECDH needs "DERIVE" but no any kind of "SIGN" + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage ECDH_usages_mask[] = { + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN, + org.mozilla.jss.crypto.KeyPairGeneratorSpi.Usage.SIGN_RECOVER, + }; + + do { + if (ct.equals("sslserver") && sslType.equalsIgnoreCase("ECDH")) { + CMS.debug("SizePanel: createECCKeypair: sslserver cert for ECDH. Make sure server.xml is set properly with -TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,+TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); + pair = CryptoUtil.generateECCKeyPair(token, curveName, + null, + ECDH_usages_mask); + } else { + if (ct.equals("sslserver")) { + CMS.debug("SizePanel: createECCKeypair: sslserver cert for ECDHE. Make sure server.xml is set properly with +TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA"); + } + pair = CryptoUtil.generateECCKeyPair(token, curveName, + null, + usages_mask); + } + + // XXX - store curve , w + byte id[] = ((org.mozilla.jss.crypto.PrivateKey) pair.getPrivate()).getUniqueID(); + String kid = CryptoUtil.byte2string(id); + config.putString(PCERT_PREFIX + ct + ".privkey.id", kid); + + // try to locate the private key + org.mozilla.jss.crypto.PrivateKey privk = + CryptoUtil.findPrivateKeyFromID(CryptoUtil.string2byte(kid)); + if (privk == null) { + CMS.debug("Found bad ECC key id " + kid); + pair = null; + } + } while (pair == null); + + CMS.debug("Public key class " + pair.getPublic().getClass().getName()); + byte encoded[] = pair.getPublic().getEncoded(); + config.putString(PCERT_PREFIX + ct + ".pubkey.encoded", + CryptoUtil.byte2string(encoded)); + + String keyAlgo = ""; + try { + keyAlgo = config.getString(PCERT_PREFIX + ct + ".signingalgorithm"); + } catch (Exception e1) { + } + + setSigningAlgorithm(ct, keyAlgo, config); + } + + public void createRSAKeyPair(String token, int keysize, IConfigStore config, String ct) + throws NoSuchAlgorithmException, NoSuchTokenException, TokenException, + CryptoManager.NotInitializedException { + /* generate key pair */ + KeyPair pair = null; + do { + pair = CryptoUtil.generateRSAKeyPair(token, keysize); + byte id[] = ((org.mozilla.jss.crypto.PrivateKey) pair.getPrivate()).getUniqueID(); + String kid = CryptoUtil.byte2string(id); + config.putString(PCERT_PREFIX + ct + ".privkey.id", kid); + // try to locate the private key + org.mozilla.jss.crypto.PrivateKey privk = + CryptoUtil.findPrivateKeyFromID(CryptoUtil.string2byte(kid)); + if (privk == null) { + CMS.debug("Found bad RSA key id " + kid); + pair = null; + } + } while (pair == null); + + byte modulus[] = ((RSAPublicKey) pair.getPublic()).getModulus().toByteArray(); + byte exponent[] = ((RSAPublicKey) pair.getPublic()).getPublicExponent().toByteArray(); + + config.putString(PCERT_PREFIX + ct + ".pubkey.modulus", + CryptoUtil.byte2string(modulus)); + config.putString(PCERT_PREFIX + ct + ".pubkey.exponent", + CryptoUtil.byte2string(exponent)); + + String keyAlgo = ""; + try { + keyAlgo = config.getString(PCERT_PREFIX + ct + ".signingalgorithm"); + } catch (Exception e1) { + } + + setSigningAlgorithm(ct, keyAlgo, config); + } + + public void setSigningAlgorithm(String ct, String keyAlgo, IConfigStore config) { + String systemType = ""; + try { + systemType = config.getString("preop.system.name"); + } catch (Exception e1) { + } + if (systemType.equalsIgnoreCase("CA")) { + if (ct.equals("signing")) { + config.putString("ca.signing.defaultSigningAlgorithm", + keyAlgo); + config.putString("ca.crl.MasterCRL.signingAlgorithm", + keyAlgo); + } else if (ct.equals("ocsp_signing")) { + config.putString("ca.ocsp_signing.defaultSigningAlgorithm", + keyAlgo); + } + } else if (systemType.equalsIgnoreCase("OCSP")) { + if (ct.equals("signing")) { + config.putString("ocsp.signing.defaultSigningAlgorithm", + keyAlgo); + } + } else if (systemType.equalsIgnoreCase("KRA") || + systemType.equalsIgnoreCase("DRM")) { + if (ct.equals("transport")) { + config.putString("kra.transportUnit.signingAlgorithm", keyAlgo); + } + } + } + + public void initParams(HttpServletRequest request, Context context) + throws IOException { + IConfigStore config = CMS.getConfigStore(); + String s = ""; + try { + context.put("title", "Key Pairs"); + + s = config.getString("preop.subsystem.select", ""); + context.put("select", s); + + s = config.getString("preop.hierarchy.select", "root"); + context.put("hselect", s); + + s = config.getString("preop.ecc.algorithm.list", "SHA256withEC,SHA1withEC,SHA384withEC,SHA512withEC"); + context.put("ecclist", s); + + s = + config.getString("preop.rsa.algorithm.list", + "SHA256withRSA,SHA1withRSA,SHA512withRSA,MD5withRSA,MD2withRSA"); + context.put("rsalist", s); + + s = config.getString("keys.ecc.curve.list", "nistp256"); + context.put("curvelist", s); + + s = config.getString("keys.ecc.curve.display.list", "nistp256"); + context.put("displaycurvelist", s); + + s = config.getString("pkicreate.subsystem_type"); + context.put("subsystemtype", s); + + } catch (Exception e) { + CMS.debug("SizePanel(): initParams: unable to set all initial parameters:" + e); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + try { + initParams(request, context); + } catch (IOException e) { + } + + context.put("certs", mCerts); + context.put("show_signing", mShowSigning ? "true" : "false"); + context.put("default_keysize", default_rsa_key_size); + context.put("default_ecc_curvename", default_ecc_curve_name); + + context.put("panel", "admin/console/config/sizepanel.vm"); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java b/base/common/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java new file mode 100644 index 000000000..2372b3094 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java @@ -0,0 +1,146 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISecurityDomainSessionTable; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.xml.XMLObject; + +public class TokenAuthenticate extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -9098593390260940853L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + public TokenAuthenticate() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + IConfigStore config = CMS.getConfigStore(); + + String sessionId = httpReq.getParameter("sessionID"); + CMS.debug("TokenAuthentication: sessionId=" + sessionId); + String givenHost = httpReq.getParameter("hostname"); + CMS.debug("TokenAuthentication: givenHost=" + givenHost); + + boolean checkIP = false; + try { + checkIP = config.getBoolean("securitydomain.checkIP", false); + } catch (Exception e) { + } + + ISecurityDomainSessionTable table = CMS.getSecurityDomainSessionTable(); + String uid = ""; + String gid = ""; + CMS.debug("TokenAuthentication: checking session in the session table"); + if (table.isSessionIdExist(sessionId)) { + CMS.debug("TokenAuthentication: found session"); + if (checkIP) { + String hostname = table.getIP(sessionId); + if (!hostname.equals(givenHost)) { + CMS.debug("TokenAuthentication: hostname=" + hostname + " and givenHost=" + + givenHost + " are different"); + CMS.debug("TokenAuthenticate authenticate failed, wrong hostname."); + outputError(httpResp, "Error: Failed Authentication"); + return; + } + } + + uid = table.getUID(sessionId); + gid = table.getGroup(sessionId); + } else { + CMS.debug("TokenAuthentication: session not found"); + CMS.debug("TokenAuthentication authenticate failed, session id does not exist."); + outputError(httpResp, "Error: Failed Authentication"); + return; + } + + CMS.debug("TokenAuthenticate successfully authenticate"); + try { + XMLObject xmlObj = null; + + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + xmlObj.addItemToContainer(root, "uid", uid); + xmlObj.addItemToContainer(root, "gid", gid); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java new file mode 100644 index 000000000..f3df51bd1 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java @@ -0,0 +1,203 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +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.base.IConfigStore; +import com.netscape.certsrv.ca.ICAService; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.connector.IConnector; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.xml.XMLObject; + +public class UpdateConnector extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 972871860008509849L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + + public UpdateConnector() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("UpdateConnector: initializing..."); + super.init(sc); + CMS.debug("UpdateConnector: done initializing..."); + } + + /** + * Process the HTTP request. + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("UpdateConnector: processing..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = null; + try { + authToken = authenticate(cmsReq); + CMS.debug("UpdateConnector authentication successful."); + } catch (Exception e) { + CMS.debug("UpdateConnector: authentication failed."); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_BAD_SERV_OUT_STREAM", "", + e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + if (authToken == null) { + CMS.debug("UpdateConnector: authentication failed."); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + + AuthzToken authzToken = null; + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, + "modify"); + CMS.debug("UpdateConnector authorization successful."); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + "Error: Encountered problem during authorization."); + return; + } + + if (authzToken == null) { + outputError(httpResp, "Error: Not authorized"); + return; + } + + IConfigStore cs = CMS.getConfigStore(); + + @SuppressWarnings("unchecked") + Enumeration<String> list = httpReq.getParameterNames(); + while (list.hasMoreElements()) { + String name = list.nextElement(); + String val = httpReq.getParameter(name); + if (name != null && name.startsWith("ca.connector")) { + CMS.debug("Adding connector update name=" + name + " val=" + val); + cs.putString(name, val); + } else { + CMS.debug("Skipping connector update name=" + name + " val=" + val); + } + } + + try { + String nickname = cs.getString("ca.subsystem.nickname", ""); + String tokenname = cs.getString("ca.subsystem.tokenname", ""); + if (!tokenname.equals("Internal Key Storage Token")) + nickname = tokenname + ":" + nickname; + cs.putString("ca.connector.KRA.nickName", nickname); + cs.commit(false); + } catch (Exception e) { + } + + // start the connector + try { + ICertificateAuthority ca = (ICertificateAuthority) + CMS.getSubsystem("ca"); + ICAService caService = (ICAService) ca.getCAService(); + IConnector kraConnector = caService.getConnector( + cs.getSubStore("ca.connector.KRA")); + caService.setKRAConnector(kraConnector); + kraConnector.start(); + } catch (Exception e) { + CMS.debug("Failed to start connector " + e); + } + + // send success status back to the requestor + try { + CMS.debug("UpdateConnector: Sending response"); + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("UpdateConnector: Failed to send the XML output"); + } + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java new file mode 100644 index 000000000..a2b6ebc72 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java @@ -0,0 +1,568 @@ +// --- 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.csadmin; + +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPAttributeSet; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPModification; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +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.base.IConfigStore; +import com.netscape.certsrv.ldap.ILdapConnFactory; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.xml.XMLObject; + +public class UpdateDomainXML extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 4059169588555717548L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE = + "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1"; + private final static String LOGGING_SIGNED_AUDIT_CONFIG_ROLE = + "LOGGING_SIGNED_AUDIT_CONFIG_ROLE_3"; + + public UpdateDomainXML() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("UpdateDomainXML: initializing..."); + super.init(sc); + CMS.debug("UpdateDomainXML: done initializing..."); + } + + private String remove_from_ldap(String dn) { + CMS.debug("UpdateDomainXML: delete_from_ldap: starting dn: " + dn); + String status = SUCCESS; + ILdapConnFactory connFactory = null; + LDAPConnection conn = null; + IConfigStore cs = CMS.getConfigStore(); + + try { + IConfigStore ldapConfig = cs.getSubStore("internaldb"); + connFactory = CMS.getLdapBoundConnFactory(); + connFactory.init(ldapConfig); + conn = connFactory.getConn(); + conn.delete(dn); + } catch (LDAPException e) { + if (e.getLDAPResultCode() != LDAPException.NO_SUCH_OBJECT) { + status = FAILED; + CMS.debug("Failed to delete entry" + e.toString()); + } + } catch (Exception e) { + CMS.debug("Failed to delete entry" + e.toString()); + } finally { + try { + if ((conn != null) && (connFactory != null)) { + CMS.debug("Releasing ldap connection"); + connFactory.returnConn(conn); + } + } catch (Exception e) { + CMS.debug("Error releasing the ldap connection" + e.toString()); + } + } + return status; + } + + private String modify_ldap(String dn, LDAPModification mod) { + CMS.debug("UpdateDomainXML: modify_ldap: starting dn: " + dn); + String status = SUCCESS; + ILdapConnFactory connFactory = null; + LDAPConnection conn = null; + IConfigStore cs = CMS.getConfigStore(); + + try { + IConfigStore ldapConfig = cs.getSubStore("internaldb"); + connFactory = CMS.getLdapBoundConnFactory(); + connFactory.init(ldapConfig); + conn = connFactory.getConn(); + conn.modify(dn, mod); + } catch (LDAPException e) { + if (e.getLDAPResultCode() != LDAPException.NO_SUCH_OBJECT) { + status = FAILED; + CMS.debug("Failed to modify entry" + e.toString()); + } + } catch (Exception e) { + CMS.debug("Failed to modify entry" + e.toString()); + } finally { + try { + if ((conn != null) && (connFactory != null)) { + CMS.debug("Releasing ldap connection"); + connFactory.returnConn(conn); + } + } catch (Exception e) { + CMS.debug("Error releasing the ldap connection" + e.toString()); + } + } + return status; + } + + private String add_to_ldap(LDAPEntry entry, String dn) { + CMS.debug("UpdateDomainXML: add_to_ldap: starting"); + String status = SUCCESS; + ILdapConnFactory connFactory = null; + LDAPConnection conn = null; + IConfigStore cs = CMS.getConfigStore(); + + try { + IConfigStore ldapConfig = cs.getSubStore("internaldb"); + connFactory = CMS.getLdapBoundConnFactory(); + connFactory.init(ldapConfig); + conn = connFactory.getConn(); + conn.add(entry); + } catch (LDAPException e) { + if (e.getLDAPResultCode() == LDAPException.ENTRY_ALREADY_EXISTS) { + CMS.debug("UpdateDomainXML: Entry already exists"); + try { + conn.delete(dn); + conn.add(entry); + } catch (LDAPException ee) { + CMS.debug("UpdateDomainXML: Error when replacing existing entry " + ee.toString()); + status = FAILED; + } + } else { + CMS.debug("UpdateDomainXML: Failed to update ldap domain info. Exception: " + e.toString()); + status = FAILED; + } + } catch (Exception e) { + CMS.debug("Failed to add entry" + e.toString()); + } finally { + try { + if ((conn != null) && (connFactory != null)) { + CMS.debug("Releasing ldap connection"); + connFactory.returnConn(conn); + } + } catch (Exception e) { + CMS.debug("Error releasing the ldap connection" + e.toString()); + } + } + return status; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param op 'downloadBIN' - return the binary certificate chain + * <li>http.param op 'displayIND' - display pretty-print of certificate chain components + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("UpdateDomainXML: processing..."); + String status = SUCCESS; + String status2 = SUCCESS; + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + CMS.debug("UpdateDomainXML process: authentication starts"); + IAuthToken authToken = null; + try { + authToken = authenticate(cmsReq); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authenticated"); + return; + } + if (authToken == null) { + CMS.debug("UpdateDomainXML process: authToken is null"); + outputError(httpResp, AUTH_FAILURE, "Error: not authenticated"); + return; + } + CMS.debug("UpdateDomainXML process: authentication done"); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, + "modify"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, AUTH_FAILURE, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + AUTH_FAILURE, + "Error: Encountered problem during authorization."); + return; + } + if (authzToken == null) { + CMS.debug("UpdateDomainXML process: authorization error"); + outputError(httpResp, AUTH_FAILURE, "Error: Not authorized"); + return; + } + + String list = httpReq.getParameter("list"); + String type = httpReq.getParameter("type"); + String host = httpReq.getParameter("host"); + String name = httpReq.getParameter("name"); + String sport = httpReq.getParameter("sport"); + String agentsport = httpReq.getParameter("agentsport"); + String adminsport = httpReq.getParameter("adminsport"); + String eecaport = httpReq.getParameter("eeclientauthsport"); + String httpport = httpReq.getParameter("httpport"); + String domainmgr = httpReq.getParameter("dm"); + String clone = httpReq.getParameter("clone"); + String operation = httpReq.getParameter("operation"); + + // ensure required parameters are present + // especially important for DS syntax checking + String missing = ""; + if ((host == null) || host.equals("")) { + missing += " host "; + } + if ((name == null) || name.equals("")) { + missing += " name "; + } + if ((sport == null) || sport.equals("")) { + missing += " sport "; + } + if ((type == null) || type.equals("")) { + missing += " type "; + } + if ((clone == null) || clone.equals("")) { + clone = "false"; + } + + if (!missing.equals("")) { + CMS.debug("UpdateDomainXML process: required parameters:" + missing + + "not provided in request"); + outputError(httpResp, "Error: required parameters: " + missing + + "not provided in request"); + return; + } + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditParams = "host;;" + host + "+name;;" + name + "+sport;;" + sport + + "+clone;;" + clone + "+type;;" + type; + if (operation != null) { + auditParams += "+operation;;" + operation; + } else { + auditParams += "+operation;;add"; + } + + String basedn = null; + String secstore = null; + + IConfigStore cs = CMS.getConfigStore(); + + try { + basedn = cs.getString("internaldb.basedn"); + secstore = cs.getString("securitydomain.store"); + } catch (Exception e) { + CMS.debug("Unable to determine security domain name or basedn. Please run the domaininfo migration script"); + } + + if ((basedn != null) && (secstore != null) && (secstore.equals("ldap"))) { + // update in ldap + + LDAPEntry entry = null; + String listName = type + "List"; + String cn = host + ":"; + + if ((adminsport != null) && (adminsport != "")) { + cn += adminsport; + } else { + cn += sport; + } + + String dn = "cn=" + cn + ",cn=" + listName + ",ou=Security Domain," + basedn; + CMS.debug("UpdateDomainXML: updating LDAP entry: " + dn); + + LDAPAttributeSet attrs = null; + attrs = new LDAPAttributeSet(); + attrs.add(new LDAPAttribute("objectclass", "top")); + attrs.add(new LDAPAttribute("objectclass", "pkiSubsystem")); + attrs.add(new LDAPAttribute("cn", cn)); + attrs.add(new LDAPAttribute("Host", host)); + attrs.add(new LDAPAttribute("SecurePort", sport)); + + if ((agentsport != null) && (!agentsport.equals(""))) { + attrs.add(new LDAPAttribute("SecureAgentPort", agentsport)); + } + if ((adminsport != null) && (!adminsport.equals(""))) { + attrs.add(new LDAPAttribute("SecureAdminPort", adminsport)); + } + if ((httpport != null) && (!httpport.equals(""))) { + attrs.add(new LDAPAttribute("UnSecurePort", httpport)); + } + if ((eecaport != null) && (!eecaport.equals(""))) { + attrs.add(new LDAPAttribute("SecureEEClientAuthPort", eecaport)); + } + if ((domainmgr != null) && (!domainmgr.equals(""))) { + attrs.add(new LDAPAttribute("DomainManager", domainmgr.toUpperCase())); + } + attrs.add(new LDAPAttribute("clone", clone.toUpperCase())); + attrs.add(new LDAPAttribute("SubsystemName", name)); + entry = new LDAPEntry(dn, attrs); + + if ((operation != null) && (operation.equals("remove"))) { + status = remove_from_ldap(dn); + String adminUserDN; + if ((agentsport != null) && (!agentsport.equals(""))) { + adminUserDN = "uid=" + type + "-" + host + "-" + agentsport + ",ou=People," + basedn; + } else { + adminUserDN = "uid=" + type + "-" + host + "-" + sport + ",ou=People," + basedn; + } + String userAuditParams = "Scope;;users+Operation;;OP_DELETE+source;;UpdateDomainXML" + + "+resource;;" + adminUserDN; + if (status.equals(SUCCESS)) { + // remove the user for this subsystem's admin + status2 = remove_from_ldap(adminUserDN); + if (status2.equals(SUCCESS)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + userAuditParams); + audit(auditMessage); + + // remove this user from the subsystem group + userAuditParams = "Scope;;groups+Operation;;OP_DELETE_USER" + + "+source;;UpdateDomainXML" + + "+resource;;Subsystem Group+user;;" + adminUserDN; + dn = "cn=Subsystem Group, ou=groups," + basedn; + LDAPModification mod = new LDAPModification(LDAPModification.DELETE, + new LDAPAttribute("uniqueMember", adminUserDN)); + status2 = modify_ldap(dn, mod); + if (status2.equals(SUCCESS)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.SUCCESS, + userAuditParams); + } else { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + userAuditParams); + } + audit(auditMessage); + } else { // error deleting user + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_ROLE, + auditSubjectID, + ILogger.FAILURE, + userAuditParams); + audit(auditMessage); + } + } + } else { + status = add_to_ldap(entry, dn); + } + } else { + // update the domain.xml file + String path = CMS.getConfigStore().getString("instanceRoot", "") + + "/conf/domain.xml"; + + CMS.debug("UpdateDomainXML: got path=" + path); + + try { + // using domain.xml file + CMS.debug("UpdateDomainXML: Inserting new domain info"); + XMLObject parser = new XMLObject(new FileInputStream(path)); + Node n = parser.getContainer(list); + int count = 0; + + if ((operation != null) && (operation.equals("remove"))) { + // delete node + Document doc = parser.getDocument(); + NodeList nodeList = doc.getElementsByTagName(type); + int len = nodeList.getLength(); + + for (int i = 0; i < len; i++) { + Node nn = (Node) nodeList.item(i); + Vector<String> v_name = parser.getValuesFromContainer(nn, "SubsystemName"); + Vector<String> v_host = parser.getValuesFromContainer(nn, "Host"); + Vector<String> v_adminport = parser.getValuesFromContainer(nn, "SecureAdminPort"); + if ((v_name.elementAt(0).equals(name)) && (v_host.elementAt(0).equals(host)) + && (v_adminport.elementAt(0).equals(adminsport))) { + Node parent = nn.getParentNode(); + parent.removeChild(nn); + count--; + break; + } + } + } else { + // add node + Node parent = parser.createContainer(n, type); + parser.addItemToContainer(parent, "SubsystemName", name); + parser.addItemToContainer(parent, "Host", host); + parser.addItemToContainer(parent, "SecurePort", sport); + parser.addItemToContainer(parent, "SecureAgentPort", agentsport); + parser.addItemToContainer(parent, "SecureAdminPort", adminsport); + parser.addItemToContainer(parent, "SecureEEClientAuthPort", eecaport); + parser.addItemToContainer(parent, "UnSecurePort", httpport); + parser.addItemToContainer(parent, "DomainManager", domainmgr.toUpperCase()); + parser.addItemToContainer(parent, "Clone", clone.toUpperCase()); + count++; + } + //update count + + String countS = ""; + NodeList nlist = n.getChildNodes(); + Node countnode = null; + for (int i = 0; i < nlist.getLength(); i++) { + Element nn = (Element) nlist.item(i); + String tagname = nn.getTagName(); + if (tagname.equals("SubsystemCount")) { + countnode = nn; + NodeList nlist1 = nn.getChildNodes(); + Node nn1 = nlist1.item(0); + countS = nn1.getNodeValue(); + break; + } + } + + CMS.debug("UpdateDomainXML process: SubsystemCount=" + countS); + try { + count += Integer.parseInt(countS); + } catch (Exception ee) { + } + + n.removeChild(countnode); + parser.addItemToContainer(n, "SubsystemCount", "" + count); + + // recreate domain.xml + CMS.debug("UpdateDomainXML: Recreating domain.xml"); + byte[] b = parser.toByteArray(); + FileOutputStream fos = new FileOutputStream(path); + fos.write(b); + fos.close(); + } catch (Exception e) { + CMS.debug("Failed to update domain.xml file" + e.toString()); + status = FAILED; + } + + } + + if (status.equals(SUCCESS)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE, + auditSubjectID, + ILogger.SUCCESS, + auditParams); + } else { + // what if already exists or already deleted + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE, + auditSubjectID, + ILogger.FAILURE, + auditParams); + } + audit(auditMessage); + + if (status.equals(SUCCESS) && status2.equals(SUCCESS)) { + status = SUCCESS; + } else { + status = FAILED; + } + + try { + // send success status back to the requestor + CMS.debug("UpdateDomainXML: Sending response"); + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", status); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("UpdateDomainXML: Failed to send the XML output" + e.toString()); + } + } + + protected String securityDomainXMLtoLDAP(String xmltag) { + if (xmltag.equals("Host")) + return "host"; + else + return xmltag; + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java new file mode 100644 index 000000000..894afa5ff --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java @@ -0,0 +1,290 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +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.base.IConfigStore; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.repository.IRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.xml.XMLObject; + +public class UpdateNumberRange extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -1584171713024263331L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + private final static String LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER = + "LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER_1"; + + public UpdateNumberRange() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("UpdateNumberRange: initializing..."); + super.init(sc); + CMS.debug("UpdateNumberRange: done initializing..."); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param op 'downloadBIN' - return the binary certificate chain + * <li>http.param op 'displayIND' - display pretty-print of certificate chain components + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("UpdateNumberRange: processing..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + CMS.debug("UpdateNumberRange process: authentication starts"); + IAuthToken authToken = authenticate(cmsReq); + if (authToken == null) { + CMS.debug("UpdateNumberRange process: authToken is null"); + outputError(httpResp, AUTH_FAILURE, "Error: not authenticated"); + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, + "modify"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + "Error: Encountered problem during authorization."); + return; + } + if (authzToken == null) { + outputError(httpResp, "Error: Not authorized"); + return; + } + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditParams = "source;;updateNumberRange"; + + try { + String type = httpReq.getParameter("type"); + IConfigStore cs = CMS.getConfigStore(); + String cstype = cs.getString("cs.type", ""); + + auditParams += "+type;;" + type; + + BigInteger beginNum = null; + BigInteger endNum = null; + BigInteger oneNum = new BigInteger("1"); + String endNumConfig = null; + String cloneNumConfig = null; + String nextEndConfig = null; + int radix = 10; + + IRepository repo = null; + if (cstype.equals("KRA")) { + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem( + IKeyRecoveryAuthority.ID); + if (type.equals("request")) { + repo = kra.getRequestQueue().getRequestRepository(); + } else if (type.equals("serialNo")) { + repo = kra.getKeyRepository(); + } else if (type.equals("replicaId")) { + repo = kra.getReplicaRepository(); + } + } else { // CA + ICertificateAuthority ca = (ICertificateAuthority) CMS.getSubsystem( + ICertificateAuthority.ID); + if (type.equals("request")) { + repo = ca.getRequestQueue().getRequestRepository(); + } else if (type.equals("serialNo")) { + repo = ca.getCertificateRepository(); + } else if (type.equals("replicaId")) { + repo = ca.getReplicaRepository(); + } + } + + // checkRanges for replicaID - we do this each time a replica is created. + // This needs to be done beforehand to ensure that we always have enough + // replica numbers + if (type.equals("replicaId")) { + CMS.debug("Checking replica number ranges"); + repo.checkRanges(); + } + + if (type.equals("request")) { + radix = 10; + endNumConfig = "dbs.endRequestNumber"; + cloneNumConfig = "dbs.requestCloneTransferNumber"; + nextEndConfig = "dbs.nextEndRequestNumber"; + } else if (type.equals("serialNo")) { + radix = 16; + endNumConfig = "dbs.endSerialNumber"; + cloneNumConfig = "dbs.serialCloneTransferNumber"; + nextEndConfig = "dbs.nextEndSerialNumber"; + } else if (type.equals("replicaId")) { + radix = 10; + endNumConfig = "dbs.endReplicaNumber"; + cloneNumConfig = "dbs.replicaCloneTransferNumber"; + nextEndConfig = "dbs.nextEndReplicaNumber"; + } + + String endNumStr = cs.getString(endNumConfig, ""); + endNum = new BigInteger(endNumStr, radix); + String decrementStr = cs.getString(cloneNumConfig, ""); + BigInteger decrement = new BigInteger(decrementStr, radix); + beginNum = endNum.subtract(decrement).add(oneNum); + + if (beginNum.compareTo(repo.getTheSerialNumber()) < 0) { + String nextEndNumStr = cs.getString(nextEndConfig, ""); + BigInteger endNum2 = new BigInteger(nextEndNumStr, radix); + CMS.debug("Transferring from the end of on-deck range"); + String newValStr = endNum2.subtract(decrement).toString(radix); + repo.setNextMaxSerial(newValStr); + cs.putString(nextEndConfig, newValStr); + beginNum = endNum2.subtract(decrement).add(oneNum); + endNum = endNum2; + } else { + CMS.debug("Transferring from the end of the current range"); + String newValStr = beginNum.subtract(oneNum).toString(radix); + repo.setMaxSerial(newValStr); + cs.putString(endNumConfig, newValStr); + } + + if (beginNum == null) { + CMS.debug("UpdateNumberRange::process() - " + + "beginNum is null!"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER, + auditSubjectID, + ILogger.FAILURE, + auditParams); + audit(auditMessage); + return; + } + + // Enable serial number management in master for certs and requests + if (type.equals("replicaId")) { + repo.setEnableSerialMgmt(true); + } + + // insert info + CMS.debug("UpdateNumberRange: Sending response"); + + // send success status back to the requestor + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + xmlObj.addItemToContainer(root, "beginNumber", beginNum.toString(radix)); + xmlObj.addItemToContainer(root, "endNumber", endNum.toString(radix)); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + cs.commit(false); + + auditParams += "+beginNumber;;" + beginNum.toString(radix) + + "+endNumber;;" + endNum.toString(radix); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER, + auditSubjectID, + ILogger.SUCCESS, + auditParams); + audit(auditMessage); + + } catch (Exception e) { + CMS.debug("UpdateNumberRange: Failed to update number range. Exception: " + e.toString()); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_SERIAL_NUMBER, + auditSubjectID, + ILogger.FAILURE, + auditParams); + audit(auditMessage); + + outputError(httpResp, "Error: Failed to update number range."); + } + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java new file mode 100644 index 000000000..2d3e33f9a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java @@ -0,0 +1,182 @@ +// --- 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.csadmin; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.w3c.dom.Node; + +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.base.IConfigStore; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.xml.XMLObject; + +public class UpdateOCSPConfig extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 42812270761684404L; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + + public UpdateOCSPConfig() { + super(); + } + + /** + * initialize the servlet. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + CMS.debug("UpdateOCSPConfig: initializing..."); + super.init(sc); + CMS.debug("UpdateOCSPConfig: done initializing..."); + } + + protected void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("UpdateOCSPConfig: processing..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + CMS.debug("UpdateOCSPConfig process: authentication starts"); + IAuthToken authToken = authenticate(cmsReq); + if (authToken == null) { + CMS.debug("UpdateOCSPConfig process: authToken is null"); + outputError(httpResp, AUTH_FAILURE, "Error: not authenticated"); + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, mAuthzResourceName, + "modify"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, "Error: Not authorized"); + return; + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + outputError(httpResp, + "Error: Encountered problem during authorization."); + return; + } + if (authzToken == null) { + outputError(httpResp, "Error: Not authorized"); + return; + } + + IConfigStore cs = CMS.getConfigStore(); + String nickname = ""; + + // get nickname + try { + nickname = cs.getString("ca.subsystem.nickname", ""); + String tokenname = cs.getString("ca.subsystem.tokenname", ""); + if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) + nickname = tokenname + ":" + nickname; + } catch (Exception e) { + } + + CMS.debug("UpdateOCSPConfig process: nickname=" + nickname); + + String ocsphost = httpReq.getParameter("ocsp_host"); + String ocspport = httpReq.getParameter("ocsp_port"); + try { + cs.putString("ca.publish.enable", "true"); + cs.putString("ca.publish.publisher.instance.OCSPPublisher.host", + ocsphost); + cs.putString("ca.publish.publisher.instance.OCSPPublisher.port", + ocspport); + cs.putString("ca.publish.publisher.instance.OCSPPublisher.nickName", + nickname); + cs.putString("ca.publish.publisher.instance.OCSPPublisher.path", + "/ocsp/agent/ocsp/addCRL"); + cs.putString("ca.publish.publisher.instance.OCSPPublisher.pluginName", "OCSPPublisher"); + cs.putString("ca.publish.publisher.instance.OCSPPublisher.enableClientAuth", "true"); + cs.putString("ca.publish.rule.instance.ocsprule.enable", "true"); + cs.putString("ca.publish.rule.instance.ocsprule.mapper", "NoMap"); + cs.putString("ca.publish.rule.instance.ocsprule.pluginName", "Rule"); + cs.putString("ca.publish.rule.instance.ocsprule.publisher", + "OCSPPublisher"); + cs.putString("ca.publish.rule.instance.ocsprule.type", "crl"); + cs.commit(false); + // insert info + CMS.debug("UpdateOCSPConfig: Sending response"); + + // send success status back to the requestor + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("UpdateOCSPConfig: Failed to update OCSP configuration. Exception: " + e.toString()); + outputError(httpResp, "Error: Failed to update OCSP configuration."); + } + } + + protected void setDefaultTemplates(ServletConfig sc) { + } + + protected void renderTemplate( + CMSRequest cmsReq, String templateName, ICMSTemplateFiller filler) + throws IOException {// do nothing + } + + protected void renderResult(CMSRequest cmsReq) throws IOException {// do nothing, ie, it will not return the default javascript. + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java b/base/common/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java new file mode 100644 index 000000000..4224c4ebf --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java @@ -0,0 +1,128 @@ +// --- 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.csadmin; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.cms.servlet.wizard.WizardServlet; + +public class WelcomePanel extends WizardPanelBase { + + public WelcomePanel() { + } + + /** + * Initializes this panel. + */ + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + setPanelNo(panelno); + setName("Welcome"); + setId(id); + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putBoolean("preop.welcome.done", false); + } + + public boolean isPanelDone() { + IConfigStore cs = CMS.getConfigStore(); + try { + return cs.getBoolean("preop.welcome.done"); + } catch (EBaseException e) { + } + return false; + } + + public PropertySet getUsage() { + PropertySet set = new PropertySet(); + + /* XXX */ + + return set; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + IConfigStore cs = CMS.getConfigStore(); + CMS.debug("WelcomePanel: display()"); + context.put("title", "Welcome"); + try { + context.put("cstype", cs.getString("cs.type")); + context.put("wizardname", cs.getString("preop.wizard.name")); + context.put("panelname", + cs.getString("preop.system.fullname") + " Configuration Wizard"); + context.put("systemname", + cs.getString("preop.system.name")); + context.put("fullsystemname", + cs.getString("preop.system.fullname")); + context.put("productname", + cs.getString("preop.product.name")); + context.put("productversion", + cs.getString("preop.product.version")); + } catch (EBaseException e) { + } + context.put("panel", "admin/console/config/welcomepanel.vm"); + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore cs = CMS.getConfigStore(); + try { + cs.putBoolean("preop.welcome.done", true); + cs.commit(false); + } catch (EBaseException e) { + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) {/* This should never be called */ + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/WelcomeServlet.java b/base/common/src/com/netscape/cms/servlet/csadmin/WelcomeServlet.java new file mode 100644 index 000000000..f5a96bc8a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/WelcomeServlet.java @@ -0,0 +1,49 @@ +// --- 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.csadmin; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; + +public class WelcomeServlet extends BaseServlet { + + /** + * + */ + private static final long serialVersionUID = 1179761802633506502L; + + public Template process(HttpServletRequest request, + HttpServletResponse response, + Context context) { + + Template template = null; + + try { + context.put("name", "Velocity Test"); + template = Velocity.getTemplate("admin/console/config/welcome.vm"); + } catch (Exception e) { + System.err.println("Exception caught: " + e.getMessage()); + } + + return template; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java b/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java new file mode 100644 index 000000000..55f7171ef --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java @@ -0,0 +1,1630 @@ +// --- 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.csadmin; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.ConnectException; +import java.net.URLEncoder; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPDN; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPSearchConstraints; +import netscape.ldap.LDAPSearchResults; + +import org.apache.velocity.context.Context; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoStore; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.pkcs11.PK11Store; +import org.mozilla.jss.ssl.SSLCertificateApprovalCallback; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.property.PropertySet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.wizard.IWizardPanel; +import com.netscape.cms.servlet.wizard.WizardServlet; +import com.netscape.cmsutil.crypto.CryptoUtil; +import com.netscape.cmsutil.http.HttpClient; +import com.netscape.cmsutil.http.HttpRequest; +import com.netscape.cmsutil.http.HttpResponse; +import com.netscape.cmsutil.http.JssSSLSocketFactory; +import com.netscape.cmsutil.xml.XMLObject; + +public class WizardPanelBase implements IWizardPanel { + public static String PCERT_PREFIX = "preop.cert."; + public static String SUCCESS = "0"; + public static String FAILURE = "1"; + public static String AUTH_FAILURE = "2"; + + /** + * Definition for static variables in CS.cfg + */ + public static final String CONF_CA_CERT = "ca.signing.cert"; + public static final String CONF_CA_CERTREQ = "ca.signing.certreq"; + public static final String CONF_CA_CERTNICKNAME = "ca.signing.certnickname"; + + public static final String PRE_CONF_ADMIN_NAME = "preop.admin.name"; + public static final String PRE_CONF_AGENT_GROUP = "preop.admin.group"; + + /** + * Definition for "preop" static variables in CS.cfg + * -- "preop" config parameters should not assumed to exist after configuation + */ + + public static final String PRE_CONF_CA_TOKEN = "preop.module.token"; + public static final String PRE_CA_TYPE = "preop.ca.type"; + public static final String PRE_OTHER_CA = "otherca"; + public static final String PRE_ROOT_CA = "rootca"; + + private String mName = null; + private int mPanelNo = 0; + private String mId = null; + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException { + mPanelNo = panelno; + } + + public void init(WizardServlet servlet, ServletConfig config, int panelno, String id) + throws ServletException { + mPanelNo = panelno; + } + + /** + * Cleans up this panel so that isPanelDone() will return false. + */ + public void cleanUp() throws IOException { + } + + public String getName() { + return mName; + } + + public int getPanelNo() { + return mPanelNo; + } + + public void setPanelNo(int num) { + mPanelNo = num; + } + + public void setName(String name) { + mName = name; + } + + public void setId(String id) { + mId = id; + } + + public String getId() { + return mId; + } + + public PropertySet getUsage() { + PropertySet set = null; + + return set; + } + + /** + * Should we skip this panel? + */ + public boolean shouldSkip() { + return false; + } + + /** + * Is this panel done + */ + public boolean isPanelDone() { + return false; + } + + /** + * Show "Apply" button on frame? + */ + public boolean showApplyButton() { + return false; + } + + /** + * Is this a subPanel? + */ + public boolean isSubPanel() { + return false; + } + + public boolean isLoopbackPanel() { + return false; + } + + /** + * has subPanels? + */ + public boolean hasSubPanel() { + return false; + } + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context) { + } + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + } + + /** + * Retrieves locale based on the request. + */ + public Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader("accept-language"); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } + + public String getNickname(IConfigStore config, String certTag) { + String instanceID = ""; + + try { + instanceID = config.getString("instanceId", ""); + } catch (Exception e) { + } + + String nickname = certTag + "Cert cert-" + instanceID; + String preferredNickname = null; + + try { + preferredNickname = config.getString( + PCERT_PREFIX + certTag + ".nickname", null); + } catch (Exception e) { + } + + if (preferredNickname != null) { + nickname = preferredNickname; + } + return nickname; + } + + public void updateDomainXML(String hostname, int port, boolean https, + String servlet, String uri) throws IOException { + CMS.debug("WizardPanelBase updateDomainXML start hostname=" + hostname + " port=" + port); + IConfigStore cs = CMS.getConfigStore(); + String nickname = ""; + String tokenname = ""; + try { + nickname = cs.getString("preop.cert.subsystem.nickname", ""); + tokenname = cs.getString("preop.module.token", ""); + } catch (Exception e) { + } + + if (!tokenname.equals("") && + !tokenname.equals("Internal Key Storage Token") && + !tokenname.equals("internal")) { + nickname = tokenname + ":" + nickname; + } + + CMS.debug("WizardPanelBase updateDomainXML nickname=" + nickname); + CMS.debug("WizardPanelBase: start sending updateDomainXML request"); + String c = getHttpResponse(hostname, port, https, servlet, uri, nickname); + CMS.debug("WizardPanelBase: done sending updateDomainXML request"); + + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject obj = null; + try { + obj = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::updateDomainXML() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = obj.getValue("Status"); + CMS.debug("WizardPanelBase updateDomainXML: status=" + status); + + if (status.equals(SUCCESS)) { + return; + } else { + String error = obj.getValue("Error"); + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: updateDomainXML: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: updateDomainXML: " + e.toString()); + throw new IOException(e.toString()); + } + } + } + + public int getSubsystemCount(String hostname, int https_admin_port, + boolean https, String type) + throws IOException { + CMS.debug("WizardPanelBase getSubsystemCount start"); + String c = getDomainXML(hostname, https_admin_port, true); + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject obj = new XMLObject(bis); + String containerName = type + "List"; + Node n = obj.getContainer(containerName); + NodeList nlist = n.getChildNodes(); + String countS = ""; + for (int i = 0; i < nlist.getLength(); i++) { + Element nn = (Element) nlist.item(i); + String tagname = nn.getTagName(); + if (tagname.equals("SubsystemCount")) { + NodeList nlist1 = nn.getChildNodes(); + Node nn1 = nlist1.item(0); + countS = nn1.getNodeValue(); + break; + } + } + CMS.debug("WizardPanelBase getSubsystemCount: SubsystemCount=" + countS); + int num = 0; + + if (countS != null && !countS.equals("")) { + try { + num = Integer.parseInt(countS); + } catch (Exception ee) { + } + } + + return num; + } catch (Exception e) { + CMS.debug("WizardPanelBase: getSubsystemCount: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return -1; + } + + public String getDomainXML(String hostname, int https_admin_port, + boolean https) + throws IOException { + CMS.debug("WizardPanelBase getDomainXML start"); + String c = getHttpResponse(hostname, https_admin_port, https, + "/ca/admin/ca/getDomainXML", null, null); + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::getDomainXML() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase getDomainXML: status=" + status); + + if (status.equals(SUCCESS)) { + String domainInfo = parser.getValue("DomainInfo"); + + CMS.debug( + "WizardPanelBase getDomainXML: domainInfo=" + + domainInfo); + return domainInfo; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: getDomainXML: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: getDomainXML: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return null; + } + + public String getSubsystemCert(String host, int port, boolean https) + throws IOException { + CMS.debug("WizardPanelBase getSubsystemCert start"); + String c = getHttpResponse(host, port, https, + "/ca/admin/ca/getSubsystemCert", null, null); + if (c != null) { + try { + ByteArrayInputStream bis = + new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::getSubsystemCert() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + String status = parser.getValue("Status"); + if (status.equals(SUCCESS)) { + String s = parser.getValue("Cert"); + return s; + } else + return null; + } catch (Exception e) { + } + } + + return null; + } + + public void updateConnectorInfo(String host, int port, boolean https, + String content) throws IOException { + CMS.debug("WizardPanelBase updateConnectorInfo start"); + String c = getHttpResponse(host, port, https, + "/ca/admin/ca/updateConnector", content, null); + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::updateConnectorInfo() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase updateConnectorInfo: status=" + status); + + if (!status.equals(SUCCESS)) { + String error = parser.getValue("Error"); + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: updateConnectorInfo: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: updateConnectorInfo: " + e.toString()); + throw new IOException(e.toString()); + } + } + } + + public String getCertChainUsingSecureAdminPort(String hostname, + int https_admin_port, + boolean https, + ConfigCertApprovalCallback + certApprovalCallback) + throws IOException { + CMS.debug("WizardPanelBase getCertChainUsingSecureAdminPort start"); + String c = getHttpResponse(hostname, https_admin_port, https, + "/ca/admin/ca/getCertChain", null, null, + certApprovalCallback); + + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::getCertChainUsingSecureAdminPort() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase getCertChainUsingSecureAdminPort: status=" + status); + + if (status.equals(SUCCESS)) { + String certchain = parser.getValue("ChainBase64"); + + certchain = CryptoUtil.normalizeCertStr(certchain); + CMS.debug( + "WizardPanelBase getCertChainUsingSecureAdminPort: certchain=" + + certchain); + return certchain; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: getCertChainUsingSecureAdminPort: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: getCertChainUsingSecureAdminPort: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return null; + } + + public String getCertChainUsingSecureEEPort(String hostname, + int https_ee_port, + boolean https, + ConfigCertApprovalCallback + certApprovalCallback) + throws IOException { + CMS.debug("WizardPanelBase getCertChainUsingSecureEEPort start"); + String c = getHttpResponse(hostname, https_ee_port, https, + "/ca/ee/ca/getCertChain", null, null, + certApprovalCallback); + + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::getCertChainUsingSecureEEPort() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase getCertChainUsingSecureEEPort: status=" + status); + + if (status.equals(SUCCESS)) { + String certchain = parser.getValue("ChainBase64"); + + certchain = CryptoUtil.normalizeCertStr(certchain); + CMS.debug( + "WizardPanelBase getCertChainUsingSecureEEPort: certchain=" + + certchain); + return certchain; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: getCertChainUsingSecureEEPort: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: getCertChainUsingSecureEEPort: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return null; + } + + public boolean updateConfigEntries(String hostname, int port, boolean https, + String servlet, String uri, IConfigStore config, + HttpServletResponse response) throws IOException { + CMS.debug("WizardPanelBase updateConfigEntries start"); + String c = getHttpResponse(hostname, port, https, servlet, uri, null); + + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::updateConfigEntries() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase updateConfigEntries: status=" + status); + + if (status.equals(SUCCESS)) { + String cstype = ""; + try { + cstype = config.getString("cs.type", ""); + } catch (Exception e) { + CMS.debug("WizardPanelBase::updateConfigEntries() - unable to get cs.type: " + e.toString()); + } + + Document doc = parser.getDocument(); + NodeList list = doc.getElementsByTagName("name"); + int len = list.getLength(); + for (int i = 0; i < len; i++) { + Node n = list.item(i); + NodeList nn = n.getChildNodes(); + String name = nn.item(0).getNodeValue(); + Node parent = n.getParentNode(); + nn = parent.getChildNodes(); + int len1 = nn.getLength(); + String v = ""; + for (int j = 0; j < len1; j++) { + Node nv = nn.item(j); + String val = nv.getNodeName(); + if (val.equals("value")) { + NodeList n2 = nv.getChildNodes(); + if (n2.getLength() > 0) + v = n2.item(0).getNodeValue(); + break; + } + } + + if (name.equals("internaldb.basedn")) { + config.putString(name, v); + config.putString("preop.internaldb.master.basedn", v); + } else if (name.startsWith("internaldb")) { + config.putString(name.replaceFirst("internaldb", "preop.internaldb.master"), v); + } else if (name.equals("instanceId")) { + config.putString("preop.master.instanceId", v); + } else if (name.equals("cloning.cert.signing.nickname")) { + config.putString("preop.master.signing.nickname", v); + config.putString("preop.cert.signing.nickname", v); + } else if (name.equals("cloning.ocsp_signing.nickname")) { + config.putString("preop.master.ocsp_signing.nickname", v); + config.putString("preop.cert.ocsp_signing.nickname", v); + } else if (name.equals("cloning.subsystem.nickname")) { + config.putString("preop.master.subsystem.nickname", v); + config.putString("preop.cert.subsystem.nickname", v); + } else if (name.equals("cloning.transport.nickname")) { + config.putString("preop.master.transport.nickname", v); + config.putString("kra.transportUnit.nickName", v); + config.putString("preop.cert.transport.nickname", v); + } else if (name.equals("cloning.storage.nickname")) { + config.putString("preop.master.storage.nickname", v); + config.putString("kra.storageUnit.nickName", v); + config.putString("preop.cert.storage.nickname", v); + } else if (name.equals("cloning.audit_signing.nickname")) { + config.putString("preop.master.audit_signing.nickname", v); + config.putString("preop.cert.audit_signing.nickname", v); + config.putString(name, v); + } else if (name.startsWith("cloning.ca")) { + config.putString(name.replaceFirst("cloning", "preop"), v); + } else if (name.equals("cloning.signing.keyalgorithm")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + if (cstype.equals("CA")) { + config.putString("ca.crl.MasterCRL.signingAlgorithm", v); + config.putString("ca.signing.defaultSigningAlgorithm", v); + } else if (cstype.equals("OCSP")) { + config.putString("ocsp.signing.defaultSigningAlgorithm", v); + } + } else if (name.equals("cloning.transport.keyalgorithm")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + config.putString("kra.transportUnit.signingAlgorithm", v); + } else if (name.equals("cloning.ocsp_signing.keyalgorithm")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + if (cstype.equals("CA")) { + config.putString("ca.ocsp_signing.defaultSigningAlgorithm", v); + } + } else if (name.startsWith("cloning")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + } else { + config.putString(name, v); + } + } + + // set master ldap password (if it exists) temporarily in password store + // in case it is needed for replication. Not stored in password.conf. + try { + String master_pwd = config.getString("preop.internaldb.master.ldapauth.password", ""); + if (!master_pwd.equals("")) { + config.putString("preop.internaldb.master.ldapauth.bindPWPrompt", "master_internaldb"); + String passwordFile = config.getString("passwordFile"); + IConfigStore psStore = CMS.createFileConfigStore(passwordFile); + psStore.putString("master_internaldb", master_pwd); + psStore.commit(false); + } + } catch (Exception e) { + CMS.debug("updateConfigEntries: Failed to temporarily store master bindpwd: " + e.toString()); + e.printStackTrace(); + throw new IOException(e.toString()); + } + + return true; + } else if (status.equals(AUTH_FAILURE)) { + reloginSecurityDomain(response); + return false; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: updateConfigEntries: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: updateConfigEntries: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return false; + } + + public boolean authenticate(String hostname, int port, boolean https, + String servlet, String uri) throws IOException { + CMS.debug("WizardPanelBase authenticate start"); + String c = getHttpResponse(hostname, port, https, servlet, uri, null); + IConfigStore cs = CMS.getConfigStore(); + + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::authenticate() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase authenticate: status=" + status); + + if (status.equals(SUCCESS)) { + String cookie = parser.getValue("Cookie"); + cs.putString("preop.cookie", cookie); + return true; + } else { + return false; + } + } catch (Exception e) { + CMS.debug("WizardPanelBase: authenticate: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return false; + } + + public void updateOCSPConfig(String hostname, int port, boolean https, + String content, HttpServletResponse response) + throws IOException { + CMS.debug("WizardPanelBase updateOCSPConfig start"); + String c = getHttpResponse(hostname, port, https, + "/ca/ee/ca/updateOCSPConfig", content, null); + if (c == null || c.equals("")) { + CMS.debug("WizardPanelBase updateOCSPConfig: content is null."); + throw new IOException("The server you want to contact is not available"); + } else { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::updateOCSPConfig() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase updateOCSPConfig: status=" + status); + + if (status.equals(SUCCESS)) { + CMS.debug("WizardPanelBase updateOCSPConfig: Successfully update the OCSP configuration in the CA."); + } else if (status.equals(AUTH_FAILURE)) { + reloginSecurityDomain(response); + return; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase updateOCSPConfig: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase updateOCSPConfig: " + e.toString()); + throw new IOException(e.toString()); + } + } + } + + public void updateNumberRange(String hostname, int port, boolean https, + String content, String type, HttpServletResponse response) + throws IOException { + CMS.debug("WizardPanelBase updateNumberRange start host=" + hostname + + " port=" + port); + IConfigStore cs = CMS.getConfigStore(); + String cstype = ""; + try { + cstype = cs.getString("cs.type", ""); + } catch (Exception e) { + } + + cstype = toLowerCaseSubsystemType(cstype); + String c = getHttpResponse(hostname, port, https, + "/" + cstype + "/ee/" + cstype + "/updateNumberRange", content, null); + if (c == null || c.equals("")) { + CMS.debug("WizardPanelBase updateNumberRange: content is null."); + throw new IOException("The server you want to contact is not available"); + } else { + CMS.debug("content=" + c); + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::updateNumberRange() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase updateNumberRange: status=" + status); + if (status.equals(SUCCESS)) { + String beginNum = parser.getValue("beginNumber"); + String endNum = parser.getValue("endNumber"); + if (type.equals("request")) { + cs.putString("dbs.beginRequestNumber", beginNum); + cs.putString("dbs.endRequestNumber", endNum); + } else if (type.equals("serialNo")) { + cs.putString("dbs.beginSerialNumber", beginNum); + cs.putString("dbs.endSerialNumber", endNum); + } else if (type.equals("replicaId")) { + cs.putString("dbs.beginReplicaNumber", beginNum); + cs.putString("dbs.endReplicaNumber", endNum); + } + // enable serial number management in clone + cs.putString("dbs.enableSerialManagement", "true"); + cs.commit(false); + } else if (status.equals(AUTH_FAILURE)) { + reloginSecurityDomain(response); + return; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: updateNumberRange: " + e.toString()); + CMS.debug(e); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: updateNumberRange: " + e.toString()); + CMS.debug(e); + throw new IOException(e.toString()); + } + } + } + + public int getPort(String hostname, int port, boolean https, + String portServlet, boolean sport) + throws IOException { + CMS.debug("WizardPanelBase getPort start"); + String c = getHttpResponse(hostname, port, https, portServlet, + "secure=" + sport, null); + + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::getPort() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase getPort: status=" + status); + + if (status.equals(SUCCESS)) { + String portStr = parser.getValue("Port"); + + port = Integer.parseInt(portStr); + return port; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: getPort: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: getPort: " + e.toString()); + throw new IOException(e.toString()); + } + } + + return -1; + } + + public String getHttpResponse(String hostname, int port, boolean secure, + String uri, String content, String clientnickname) throws IOException { + return getHttpResponse(hostname, port, secure, uri, content, clientnickname, null); + } + + public String getHttpResponse(String hostname, int port, boolean secure, + String uri, String content, String clientnickname, + SSLCertificateApprovalCallback certApprovalCallback) + throws IOException { + HttpClient httpclient = null; + String c = null; + + try { + if (secure) { + JssSSLSocketFactory factory = null; + if (clientnickname != null && clientnickname.length() > 0) + factory = new JssSSLSocketFactory(clientnickname); + else + factory = new JssSSLSocketFactory(); + + httpclient = new HttpClient(factory, certApprovalCallback); + } else { + httpclient = new HttpClient(); + } + httpclient.connect(hostname, port); + HttpRequest httprequest = new HttpRequest(); + + httprequest.setMethod(HttpRequest.POST); + httprequest.setURI(uri); + // httprequest.setURI("/ca/ee/ca/ports"); + httprequest.setHeader("user-agent", "HTTPTool/1.0"); + // String content_c = "secure="+secure; + httprequest.setHeader("content-type", + "application/x-www-form-urlencoded"); + if (content != null && content.length() > 0) { + String content_c = content; + + httprequest.setHeader("content-length", "" + content_c.length()); + httprequest.setContent(content_c); + } + HttpResponse httpresponse = httpclient.send(httprequest); + + c = httpresponse.getContent(); + } catch (ConnectException e) { + CMS.debug("WizardPanelBase getHttpResponse: " + e.toString()); + throw new IOException("The server you tried to contact is not running."); + } catch (Exception e) { + CMS.debug("WizardPanelBase getHttpResponse: " + e.toString()); + throw new IOException(e.toString()); + } finally { + if (httpclient.connected()) { + httpclient.disconnect(); + } + } + + return c; + } + + public boolean isSDHostDomainMaster(IConfigStore config) { + String dm = "false"; + try { + String hostname = config.getString("securitydomain.host"); + int httpsadminport = config.getInteger("securitydomain.httpsadminport"); + + CMS.debug("Getting domain.xml from CA..."); + String c = getDomainXML(hostname, httpsadminport, true); + + CMS.debug("Getting DomainMaster from security domain"); + + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = new XMLObject(bis); + Document doc = parser.getDocument(); + NodeList nodeList = doc.getElementsByTagName("CA"); + + int len = nodeList.getLength(); + for (int i = 0; i < len; i++) { + Vector<String> v_hostname = + parser.getValuesFromContainer(nodeList.item(i), + "Host"); + + Vector<String> v_https_admin_port = + parser.getValuesFromContainer(nodeList.item(i), + "SecureAdminPort"); + + Vector<String> v_domain_mgr = + parser.getValuesFromContainer(nodeList.item(i), + "DomainManager"); + + if (v_hostname.elementAt(0).equals(hostname) && + v_https_admin_port.elementAt(0).equals(Integer.toString(httpsadminport))) { + dm = v_domain_mgr.elementAt(0).toString(); + break; + } + } + } catch (Exception e) { + CMS.debug(e.toString()); + } + return dm.equalsIgnoreCase("true"); + } + + public Vector<String> getMasterUrlListFromSecurityDomain(IConfigStore config, + String type, + String portType) { + Vector<String> v = new Vector<String>(); + + try { + String hostname = config.getString("securitydomain.host"); + int httpsadminport = config.getInteger("securitydomain.httpsadminport"); + + CMS.debug("Getting domain.xml from CA..."); + String c = getDomainXML(hostname, httpsadminport, true); + + CMS.debug("Type " + type); + + CMS.debug("Getting " + portType + " from Security Domain ..."); + if (!portType.equals("UnSecurePort") && + !portType.equals("SecureAgentPort") && + !portType.equals("SecurePort") && + !portType.equals("SecureAdminPort")) { + CMS.debug("getPortFromSecurityDomain: " + + "unknown port type " + portType); + return v; + } + + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = new XMLObject(bis); + Document doc = parser.getDocument(); + NodeList nodeList = doc.getElementsByTagName(type); + + // save domain name in cfg + config.putString("securitydomain.name", + parser.getValue("Name")); + + int len = nodeList.getLength(); + + CMS.debug("Len " + len); + for (int i = 0; i < len; i++) { + Vector<String> v_clone = parser.getValuesFromContainer(nodeList.item(i), + "Clone"); + String clone = (String) v_clone.elementAt(0); + if (clone.equalsIgnoreCase("true")) + continue; + Vector<String> v_name = parser.getValuesFromContainer(nodeList.item(i), + "SubsystemName"); + Vector<String> v_host = parser.getValuesFromContainer(nodeList.item(i), + "Host"); + Vector<String> v_port = parser.getValuesFromContainer(nodeList.item(i), + portType); + + v.addElement(v_name.elementAt(0) + + " - https://" + + v_host.elementAt(0) + + ":" + + v_port.elementAt(0)); + } + } catch (Exception e) { + CMS.debug(e.toString()); + } + + return v; + } + + public Vector<String> getUrlListFromSecurityDomain(IConfigStore config, + String type, + String portType) { + Vector<String> v = new Vector<String>(); + + try { + String hostname = config.getString("securitydomain.host"); + int httpsadminport = config.getInteger("securitydomain.httpsadminport"); + + CMS.debug("Getting domain.xml from CA..."); + String c = getDomainXML(hostname, httpsadminport, true); + + CMS.debug("Getting " + portType + " from Security Domain ..."); + if (!portType.equals("UnSecurePort") && + !portType.equals("SecureAgentPort") && + !portType.equals("SecurePort") && + !portType.equals("SecureAdminPort")) { + CMS.debug("getPortFromSecurityDomain: " + + "unknown port type " + portType); + return v; + } + + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = new XMLObject(bis); + Document doc = parser.getDocument(); + NodeList nodeList = doc.getElementsByTagName(type); + + // save domain name in cfg + config.putString("securitydomain.name", + parser.getValue("Name")); + + int len = nodeList.getLength(); + + CMS.debug("Len " + len); + for (int i = 0; i < len; i++) { + Vector<String> v_name = parser.getValuesFromContainer(nodeList.item(i), + "SubsystemName"); + Vector<String> v_host = parser.getValuesFromContainer(nodeList.item(i), + "Host"); + Vector<String> v_port = parser.getValuesFromContainer(nodeList.item(i), + portType); + Vector<String> v_admin_port = parser.getValuesFromContainer(nodeList.item(i), + "SecureAdminPort"); + + if (v_host.elementAt(0).equals(hostname) + && v_admin_port.elementAt(0).equals(new Integer(httpsadminport).toString())) { + // add security domain CA to the beginning of list + v.add(0, v_name.elementAt(0) + + " - https://" + + v_host.elementAt(0) + + ":" + + v_port.elementAt(0)); + } else { + v.addElement(v_name.elementAt(0) + + " - https://" + + v_host.elementAt(0) + + ":" + + v_port.elementAt(0)); + } + } + } catch (Exception e) { + CMS.debug(e.toString()); + } + + return v; + } + + // Given an HTTPS Hostname and EE port, + // retrieve the associated HTTPS Admin port + public String getSecurityDomainAdminPort(IConfigStore config, + String hostname, + String https_ee_port, + String cstype) { + String https_admin_port = new String(); + + try { + String sd_hostname = config.getString("securitydomain.host"); + int sd_httpsadminport = + config.getInteger("securitydomain.httpsadminport"); + + CMS.debug("Getting domain.xml from CA ..."); + String c = getDomainXML(sd_hostname, sd_httpsadminport, true); + + CMS.debug("Getting associated HTTPS Admin port from " + + "HTTPS Hostname '" + hostname + + "' and EE port '" + https_ee_port + "'"); + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = new XMLObject(bis); + Document doc = parser.getDocument(); + NodeList nodeList = doc.getElementsByTagName(cstype.toUpperCase()); + + int len = nodeList.getLength(); + for (int i = 0; i < len; i++) { + Vector<String> v_hostname = + parser.getValuesFromContainer(nodeList.item(i), + "Host"); + + Vector<String> v_https_ee_port = + parser.getValuesFromContainer(nodeList.item(i), + "SecurePort"); + + Vector<String> v_https_admin_port = + parser.getValuesFromContainer(nodeList.item(i), + "SecureAdminPort"); + + if (v_hostname.elementAt(0).equals(hostname) && + v_https_ee_port.elementAt(0).equals(https_ee_port)) { + https_admin_port = + v_https_admin_port.elementAt(0).toString(); + break; + } + } + } catch (Exception e) { + CMS.debug(e.toString()); + } + + return (https_admin_port); + } + + public String getSecurityDomainPort(IConfigStore config, + String portType) { + String port = new String(); + + try { + String hostname = config.getString("securitydomain.host"); + int httpsadminport = + config.getInteger("securitydomain.httpsadminport"); + + CMS.debug("Getting domain.xml from CA ..."); + String c = getDomainXML(hostname, httpsadminport, true); + + CMS.debug("Getting " + portType + " from Security Domain ..."); + if (!portType.equals("UnSecurePort") && + !portType.equals("SecureAgentPort") && + !portType.equals("SecurePort") && + !portType.equals("SecureAdminPort")) { + CMS.debug("getPortFromSecurityDomain: " + + "unknown port type " + portType); + return ""; + } + + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = new XMLObject(bis); + Document doc = parser.getDocument(); + NodeList nodeList = doc.getElementsByTagName("CA"); + + int len = nodeList.getLength(); + for (int i = 0; i < len; i++) { + Vector<String> v_admin_port = + parser.getValuesFromContainer(nodeList.item(i), + "SecureAdminPort"); + + Vector<String> v_port = null; + if (portType.equals("UnSecurePort")) { + v_port = parser.getValuesFromContainer(nodeList.item(i), + "UnSecurePort"); + } else if (portType.equals("SecureAgentPort")) { + v_port = parser.getValuesFromContainer(nodeList.item(i), + "SecureAgentPort"); + } else if (portType.equals("SecurePort")) { + v_port = parser.getValuesFromContainer(nodeList.item(i), + "SecurePort"); + } else if (portType.equals("SecureAdminPort")) { + v_port = parser.getValuesFromContainer(nodeList.item(i), + "SecureAdminPort"); + } + + if ((v_port != null) && + (v_admin_port.elementAt(0).equals( + Integer.toString(httpsadminport)))) { + port = v_port.elementAt(0).toString(); + break; + } + } + } catch (Exception e) { + CMS.debug(e.toString()); + } + + return (port); + } + + public String pingCS(String hostname, int port, boolean https, + SSLCertificateApprovalCallback certApprovalCallback) + throws IOException { + CMS.debug("WizardPanelBase pingCS: started"); + + String c = getHttpResponse(hostname, port, https, + "/ca/admin/ca/getStatus", + null, null, certApprovalCallback); + + if (c != null) { + try { + ByteArrayInputStream bis = new + ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + String state = null; + + try { + parser = new XMLObject(bis); + CMS.debug("WizardPanelBase pingCS: got XML parsed"); + state = parser.getValue("State"); + + if (state != null) { + CMS.debug("WizardPanelBase pingCS: state=" + state); + } + } catch (Exception e) { + CMS.debug("WizardPanelBase: pingCS: parser failed" + + e.toString()); + } + + return state; + } catch (Exception e) { + CMS.debug("WizardPanelBase: pingCS: " + e.toString()); + throw new IOException(e.toString()); + } + } + + CMS.debug("WizardPanelBase pingCS: stopped"); + return null; + } + + public String toLowerCaseSubsystemType(String s) { + String x = null; + if (s.equals("CA")) { + x = "ca"; + } else if (s.equals("KRA")) { + x = "kra"; + } else if (s.equals("OCSP")) { + x = "ocsp"; + } else if (s.equals("TKS")) { + x = "tks"; + } + + return x; + } + + public void getTokenInfo(IConfigStore config, String type, String host, + int https_ee_port, boolean https, Context context, + ConfigCertApprovalCallback certApprovalCallback) throws IOException { + CMS.debug("WizardPanelBase getTokenInfo start"); + String uri = "/" + type + "/ee/" + type + "/getTokenInfo"; + CMS.debug("WizardPanelBase getTokenInfo: uri=" + uri); + String c = getHttpResponse(host, https_ee_port, https, uri, null, null, + certApprovalCallback); + if (c != null) { + try { + ByteArrayInputStream bis = new ByteArrayInputStream(c.getBytes()); + XMLObject parser = null; + + try { + parser = new XMLObject(bis); + } catch (Exception e) { + CMS.debug("WizardPanelBase::getTokenInfo() - " + + "Exception=" + e.toString()); + throw new IOException(e.toString()); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase getTokenInfo: status=" + status); + + if (status.equals(SUCCESS)) { + Document doc = parser.getDocument(); + NodeList list = doc.getElementsByTagName("name"); + int len = list.getLength(); + for (int i = 0; i < len; i++) { + Node n = list.item(i); + NodeList nn = n.getChildNodes(); + String name = nn.item(0).getNodeValue(); + Node parent = n.getParentNode(); + nn = parent.getChildNodes(); + int len1 = nn.getLength(); + String v = ""; + for (int j = 0; j < len1; j++) { + Node nv = nn.item(j); + String val = nv.getNodeName(); + if (val.equals("value")) { + NodeList n2 = nv.getChildNodes(); + if (n2.getLength() > 0) + v = n2.item(0).getNodeValue(); + break; + } + } + if (name.equals("cloning.signing.nickname")) { + config.putString("preop.master.signing.nickname", v); + config.putString(type + ".cert.signing.nickname", v); + config.putString(name, v); + } else if (name.equals("cloning.ocsp_signing.nickname")) { + config.putString("preop.master.ocsp_signing.nickname", v); + config.putString(type + ".cert.ocsp_signing.nickname", v); + config.putString(name, v); + } else if (name.equals("cloning.subsystem.nickname")) { + config.putString("preop.master.subsystem.nickname", v); + config.putString(type + ".cert.subsystem.nickname", v); + config.putString(name, v); + } else if (name.equals("cloning.transport.nickname")) { + config.putString("preop.master.transport.nickname", v); + config.putString("kra.transportUnit.nickName", v); + config.putString("kra.cert.transport.nickname", v); + config.putString(name, v); + } else if (name.equals("cloning.storage.nickname")) { + config.putString("preop.master.storage.nickname", v); + config.putString("kra.storageUnit.nickName", v); + config.putString("kra.cert.storage.nickname", v); + config.putString(name, v); + } else if (name.equals("cloning.audit_signing.nickname")) { + config.putString("preop.master.audit_signing.nickname", v); + config.putString(type + ".cert.audit_signing.nickname", v); + config.putString(name, v); + } else if (name.equals("cloning.module.token")) { + config.putString("preop.module.token", v); + } else if (name.startsWith("cloning.ca")) { + config.putString(name.replaceFirst("cloning", "preop"), v); + } else if (name.startsWith("cloning")) { + config.putString(name.replaceFirst("cloning", "preop.cert"), v); + } else { + config.putString(name, v); + } + } + + // reset nicknames for system cert verification + String token = config.getString("preop.module.token", + "Internal Key Storage Token"); + if (!token.equals("Internal Key Storage Token")) { + String certlist = config.getString("preop.cert.list"); + + StringTokenizer t1 = new StringTokenizer(certlist, ","); + while (t1.hasMoreTokens()) { + String tag = t1.nextToken(); + if (tag.equals("sslserver")) + continue; + config.putString(type + ".cert." + tag + ".nickname", + token + ":" + + config.getString(type + ".cert." + tag + ".nickname", "")); + } + } + } else { + String error = parser.getValue("Error"); + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: getTokenInfo: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: getTokenInfo: " + e.toString()); + throw new IOException(e.toString()); + } + } + } + + public void importCertChain(String id) throws IOException { + CMS.debug("DisplayCertChainPanel importCertChain"); + IConfigStore config = CMS.getConfigStore(); + String configName = "preop." + id + ".pkcs7"; + String pkcs7 = ""; + + try { + pkcs7 = config.getString(configName, ""); + } catch (Exception e) { + } + + if (pkcs7.length() > 0) { + try { + CryptoUtil.importCertificateChain(pkcs7); + } catch (Exception e) { + CMS.debug("DisplayCertChainPanel importCertChain: Exception: " + e.toString()); + } + } + } + + public void updateCertChain(IConfigStore config, String name, String host, + int https_admin_port, boolean https, Context context) throws IOException { + updateCertChain(config, name, host, https_admin_port, + https, context, null); + } + + public void updateCertChain(IConfigStore config, String name, String host, + int https_admin_port, boolean https, Context context, + ConfigCertApprovalCallback certApprovalCallback) throws IOException { + String certchain = getCertChainUsingSecureAdminPort(host, + https_admin_port, + https, + certApprovalCallback); + config.putString("preop." + name + ".pkcs7", certchain); + + byte[] decoded = CryptoUtil.base64Decode(certchain); + java.security.cert.X509Certificate[] b_certchain = null; + + try { + b_certchain = CryptoUtil.getX509CertificateFromPKCS7(decoded); + } catch (Exception e) { + context.put("errorString", + "Failed to get the certificate chain."); + return; + } + + int size = 0; + if (b_certchain != null) { + size = b_certchain.length; + } + config.putInteger("preop." + name + ".certchain.size", size); + for (int i = 0; i < size; i++) { + byte[] bb = null; + + try { + bb = b_certchain[i].getEncoded(); + } catch (Exception e) { + context.put("errorString", + "Failed to get the der-encoded certificate chain."); + return; + } + config.putString("preop." + name + ".certchain." + i, + CryptoUtil.normalizeCertStr(CryptoUtil.base64Encode(bb))); + } + + try { + config.commit(false); + } catch (EBaseException e) { + } + } + + public void updateCertChainUsingSecureEEPort(IConfigStore config, + String name, String host, + int https_ee_port, + boolean https, + Context context, + ConfigCertApprovalCallback certApprovalCallback) throws IOException { + String certchain = getCertChainUsingSecureEEPort(host, https_ee_port, + https, + certApprovalCallback); + config.putString("preop." + name + ".pkcs7", certchain); + + byte[] decoded = CryptoUtil.base64Decode(certchain); + java.security.cert.X509Certificate[] b_certchain = null; + + try { + b_certchain = CryptoUtil.getX509CertificateFromPKCS7(decoded); + } catch (Exception e) { + context.put("errorString", + "Failed to get the certificate chain."); + return; + } + + int size = 0; + if (b_certchain != null) { + size = b_certchain.length; + } + config.putInteger("preop." + name + ".certchain.size", size); + for (int i = 0; i < size; i++) { + byte[] bb = null; + + try { + bb = b_certchain[i].getEncoded(); + } catch (Exception e) { + context.put("errorString", + "Failed to get the der-encoded certificate chain."); + return; + } + config.putString("preop." + name + ".certchain." + i, + CryptoUtil.normalizeCertStr(CryptoUtil.base64Encode(bb))); + } + + try { + config.commit(false); + } catch (EBaseException e) { + } + } + + public void deleteCert(String tokenname, String nickname) { + try { + CryptoManager cm = CryptoManager.getInstance(); + CryptoToken tok = cm.getTokenByName(tokenname); + CryptoStore store = tok.getCryptoStore(); + String fullnickname = nickname; + if (!tokenname.equals("") && + !tokenname.equals("Internal Key Storage Token") && + !tokenname.equals("internal")) + fullnickname = tokenname + ":" + nickname; + + CMS.debug("WizardPanelBase deleteCert: nickname=" + fullnickname); + org.mozilla.jss.crypto.X509Certificate cert = cm.findCertByNickname(fullnickname); + + if (store instanceof PK11Store) { + CMS.debug("WizardPanelBase deleteCert: this is pk11store"); + PK11Store pk11store = (PK11Store) store; + pk11store.deleteCertOnly(cert); + CMS.debug("WizardPanelBase deleteCert: cert deleted successfully"); + } + } catch (Exception e) { + CMS.debug("WizardPanelBase deleteCert: Exception=" + e.toString()); + } + } + + public void deleteEntries(LDAPSearchResults res, LDAPConnection conn, + String dn, String[] entries) { + String[] attrs = null; + LDAPSearchConstraints cons = null; + String filter = "objectclass=*"; + + try { + if (res.getCount() == 0) + return; + else { + while (res.hasMoreElements()) { + LDAPEntry entry = res.next(); + String dn1 = entry.getDN(); + LDAPSearchResults res1 = conn.search(dn1, 1, filter, attrs, true, cons); + deleteEntries(res1, conn, dn1, entries); + deleteEntry(conn, dn1, entries); + } + } + } catch (Exception ee) { + CMS.debug("WizardPanelBase deleteEntries: Exception=" + ee.toString()); + } + } + + public void deleteEntry(LDAPConnection conn, String dn, String[] entries) { + try { + for (int i = 0; i < entries.length; i++) { + if (LDAPDN.equals(dn, entries[i])) { + CMS.debug("WizardPanelBase deleteEntry: entry with this dn " + dn + " is not deleted."); + return; + } + } + + CMS.debug("WizardPanelBase deleteEntry: deleting dn=" + dn); + conn.delete(dn); + } catch (Exception e) { + CMS.debug("WizardPanelBase deleteEntry: Exception=" + e.toString()); + } + } + + public void reloginSecurityDomain(HttpServletResponse response) { + IConfigStore cs = CMS.getConfigStore(); + try { + String hostname = cs.getString("securitydomain.host", ""); + int port = cs.getInteger("securitydomain.httpsadminport", -1); + String cs_hostname = cs.getString("machineName", ""); + int cs_port = cs.getInteger("pkicreate.admin_secure_port", -1); + int panel = getPanelNo(); + String subsystem = cs.getString("cs.type", ""); + String urlVal = + "https://" + + cs_hostname + ":" + cs_port + "/" + toLowerCaseSubsystemType(subsystem) + + "/admin/console/config/wizard?p=" + panel + "&subsystem=" + subsystem; + String encodedValue = URLEncoder.encode(urlVal, "UTF-8"); + String sdurl = "https://" + hostname + ":" + port + "/ca/admin/ca/securityDomainLogin?url=" + encodedValue; + response.sendRedirect(sdurl); + } catch (Exception e) { + CMS.debug("WizardPanelBase reloginSecurityDomain: Exception=" + e.toString()); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/filter/AdminRequestFilter.java b/base/common/src/com/netscape/cms/servlet/filter/AdminRequestFilter.java new file mode 100644 index 000000000..c7532c7aa --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/filter/AdminRequestFilter.java @@ -0,0 +1,134 @@ +// --- 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) 2009 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.filter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; + +public class AdminRequestFilter implements Filter { + private static final String HTTPS_SCHEME = "https"; + private static final String HTTPS_PORT = "https_port"; + private static final String HTTPS_ROLE = "Admin"; + private static final String PROXY_PORT = "proxy_port"; + + private FilterConfig config; + + /* Create a new AdminRequestFilter */ + public AdminRequestFilter() { + } + + public void init(FilterConfig filterConfig) + throws ServletException { + this.config = filterConfig; + } + + public void doFilter(ServletRequest request, + ServletResponse response, + FilterChain chain) + throws java.io.IOException, + ServletException { + String filterName = getClass().getName(); + + String scheme = null; + int port = 0; + + String request_port = null; + String param_https_port = null; + String param_proxy_port = null; + String msg = null; + String param_active = null; + + // CMS.debug("Entering the admin filter"); + param_active = config.getInitParameter("active"); + + if (request instanceof HttpServletRequest) { + HttpServletResponse resp = (HttpServletResponse) response; + + // RFC 1738: verify that scheme is "https" + scheme = request.getScheme(); + if (!scheme.equals(HTTPS_SCHEME)) { + msg = "The scheme MUST be '" + HTTPS_SCHEME + + "', NOT '" + scheme + "'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg); + return; + } + + // Always obtain an "https" port from request + port = request.getLocalPort(); + request_port = Integer.toString(port); + + // Always obtain the "https" port passed in as a parameter + param_https_port = config.getInitParameter(HTTPS_PORT); + if (param_https_port == null) { + msg = "The <param-name> '" + HTTPS_PORT + + "' </param-name> " + "MUST be specified in 'web.xml'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg); + return; + } + + param_proxy_port = config.getInitParameter(PROXY_PORT); + boolean bad_port = false; + + // Compare the request and param "https" ports + if (!param_https_port.equals(request_port)) { + String uri = ((HttpServletRequest) request).getRequestURI(); + if (param_proxy_port != null) { + if (!param_proxy_port.equals(request_port)) { + msg = "Use HTTPS port '" + param_https_port + + "' or proxy port '" + param_proxy_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + } else { + msg = "Use HTTPS port '" + param_https_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + if (bad_port) { + CMS.debug(filterName + ": " + msg); + CMS.debug(filterName + ": uri is " + uri); + if ((param_active != null) && (param_active.equals("false"))) { + CMS.debug("Filter is disabled .. continuing"); + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg); + return; + } + } + } + } + + // CMS.debug("Exiting the admin filter"); + + chain.doFilter(request, response); + } + + public void destroy() { + } +} diff --git a/base/common/src/com/netscape/cms/servlet/filter/AgentRequestFilter.java b/base/common/src/com/netscape/cms/servlet/filter/AgentRequestFilter.java new file mode 100644 index 000000000..4225aed77 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/filter/AgentRequestFilter.java @@ -0,0 +1,134 @@ +// --- 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) 2009 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.filter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; + +public class AgentRequestFilter implements Filter { + private static final String HTTPS_SCHEME = "https"; + private static final String HTTPS_PORT = "https_port"; + private static final String HTTPS_ROLE = "Agent"; + private static final String PROXY_PORT = "proxy_port"; + + private FilterConfig config; + + /* Create a new AgentRequestFilter */ + public AgentRequestFilter() { + } + + public void init(FilterConfig filterConfig) + throws ServletException { + this.config = filterConfig; + } + + public void doFilter(ServletRequest request, + ServletResponse response, + FilterChain chain) + throws java.io.IOException, + ServletException { + String filterName = getClass().getName(); + + String scheme = null; + int port = 0; + + String request_port = null; + String param_https_port = null; + String param_proxy_port = null; + String msg = null; + + String param_active = null; + + // CMS.debug("Entering the agent filter"); + param_active = config.getInitParameter("active"); + + if (request instanceof HttpServletRequest) { + HttpServletResponse resp = (HttpServletResponse) response; + + // RFC 1738: verify that scheme is "https" + scheme = request.getScheme(); + if (!scheme.equals(HTTPS_SCHEME)) { + msg = "The scheme MUST be '" + HTTPS_SCHEME + + "', NOT '" + scheme + "'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg); + return; + } + + // Always obtain an "https" port from request + port = request.getLocalPort(); + request_port = Integer.toString(port); + + // Always obtain the "https" port passed in as a parameter + param_https_port = config.getInitParameter(HTTPS_PORT); + if (param_https_port == null) { + msg = "The <param-name> '" + HTTPS_PORT + + "' </param-name> " + "MUST be specified in 'web.xml'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg); + return; + } + + param_proxy_port = config.getInitParameter(PROXY_PORT); + boolean bad_port = false; + + // Compare the request and param "https" ports + if (!param_https_port.equals(request_port)) { + String uri = ((HttpServletRequest) request).getRequestURI(); + if (param_proxy_port != null) { + if (!param_proxy_port.equals(request_port)) { + msg = "Use HTTPS port '" + param_https_port + + "' or proxy port '" + param_proxy_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + } else { + msg = "Use HTTPS port '" + param_https_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + if (bad_port) { + CMS.debug(filterName + ": " + msg); + CMS.debug(filterName + ": uri is " + uri); + if ((param_active != null) && (param_active.equals("false"))) { + CMS.debug("Filter is disabled .. continuing"); + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg); + return; + } + } + } + } + // CMS.debug("Exiting the Agent filter"); + + chain.doFilter(request, response); + } + + public void destroy() { + } +} diff --git a/base/common/src/com/netscape/cms/servlet/filter/EEClientAuthRequestFilter.java b/base/common/src/com/netscape/cms/servlet/filter/EEClientAuthRequestFilter.java new file mode 100644 index 000000000..8c62cd311 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/filter/EEClientAuthRequestFilter.java @@ -0,0 +1,133 @@ +// --- 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) 2010 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.filter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; + +public class EEClientAuthRequestFilter implements Filter { + private static final String HTTPS_SCHEME = "https"; + private static final String HTTPS_PORT = "https_port"; + private static final String HTTPS_ROLE = "EE Client Auth"; + private static final String PROXY_PORT = "proxy_port"; + + private FilterConfig config; + + /* Create a new EEClientAuthRequestFilter */ + public EEClientAuthRequestFilter() { + } + + public void init(FilterConfig filterConfig) + throws ServletException { + this.config = filterConfig; + } + + public void doFilter(ServletRequest request, + ServletResponse response, + FilterChain chain) + throws java.io.IOException, + ServletException { + String filterName = getClass().getName(); + + String scheme = null; + int port = 0; + + String request_port = null; + String param_https_port = null; + String msg = null; + String param_active = null; + String param_proxy_port = null; + + // CMS.debug("Entering the EECA filter"); + param_active = config.getInitParameter("active"); + + if (request instanceof HttpServletRequest) { + HttpServletResponse resp = (HttpServletResponse) response; + + // RFC 1738: verify that scheme is "https" + scheme = request.getScheme(); + if (!scheme.equals(HTTPS_SCHEME)) { + msg = "The scheme MUST be '" + HTTPS_SCHEME + + "', NOT '" + scheme + "'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg); + return; + } + + // Always obtain an "https" port from request + port = request.getLocalPort(); + request_port = Integer.toString(port); + + // Always obtain the "https" port passed in as a parameter + param_https_port = config.getInitParameter(HTTPS_PORT); + if (param_https_port == null) { + msg = "The <param-name> '" + HTTPS_PORT + + "' </param-name> " + "MUST be specified in 'web.xml'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg); + return; + } + + param_proxy_port = config.getInitParameter(PROXY_PORT); + boolean bad_port = false; + + // Compare the request and param "https" ports + if (!param_https_port.equals(request_port)) { + String uri = ((HttpServletRequest) request).getRequestURI(); + if (param_proxy_port != null) { + if (!param_proxy_port.equals(request_port)) { + msg = "Use HTTPS port '" + param_https_port + + "' or proxy port '" + param_proxy_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + } else { + msg = "Use HTTPS port '" + param_https_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + if (bad_port) { + CMS.debug(filterName + ": " + msg); + CMS.debug(filterName + ": uri is " + uri); + if ((param_active != null) && (param_active.equals("false"))) { + CMS.debug("Filter is disabled .. continuing"); + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg); + return; + } + } + } + } + // CMS.debug("exiting the EECA filter"); + + chain.doFilter(request, response); + } + + public void destroy() { + } +} diff --git a/base/common/src/com/netscape/cms/servlet/filter/EERequestFilter.java b/base/common/src/com/netscape/cms/servlet/filter/EERequestFilter.java new file mode 100644 index 000000000..8a8bea01c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/filter/EERequestFilter.java @@ -0,0 +1,186 @@ +// --- 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) 2009 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.filter; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; + +public class EERequestFilter implements Filter { + private static final String HTTP_SCHEME = "http"; + private static final String HTTP_PORT = "http_port"; + private static final String HTTP_ROLE = "EE"; + private static final String HTTPS_SCHEME = "https"; + private static final String HTTPS_PORT = "https_port"; + private static final String HTTPS_ROLE = "EE"; + private static final String PROXY_PORT = "proxy_port"; + private static final String PROXY_HTTP_PORT = "proxy_http_port"; + + private FilterConfig config; + + /* Create a new EERequestFilter */ + public EERequestFilter() { + } + + public void init(FilterConfig filterConfig) + throws ServletException { + this.config = filterConfig; + } + + public void doFilter(ServletRequest request, + ServletResponse response, + FilterChain chain) + throws java.io.IOException, + ServletException { + String filterName = getClass().getName(); + + String scheme = null; + int port = 0; + + String request_port = null; + String param_http_port = null; + String param_https_port = null; + String param_proxy_port = null; + String param_proxy_http_port = null; + String msg = null; + String param_active = null; + + // CMS.debug("Entering the EE filter"); + param_active = config.getInitParameter("active"); + + if (request instanceof HttpServletRequest) { + HttpServletResponse resp = (HttpServletResponse) response; + + // RFC 1738: verify that scheme is either "http" or "https" + scheme = request.getScheme(); + if ((!scheme.equals(HTTP_SCHEME)) && + (!scheme.equals(HTTPS_SCHEME))) { + msg = "The scheme MUST be either '" + HTTP_SCHEME + + "' or '" + HTTPS_SCHEME + + "', NOT '" + scheme + "'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg); + return; + } + + // Always obtain either an "http" or an "https" port from request + port = request.getLocalPort(); + request_port = Integer.toString(port); + + // Always obtain the "http" port passed in as a parameter + param_http_port = config.getInitParameter(HTTP_PORT); + if (param_http_port == null) { + msg = "The <param-name> '" + HTTP_PORT + + "' </param-name> " + "MUST be specified in 'web.xml'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg); + return; + } + + // Always obtain the "https" port passed in as a parameter + param_https_port = config.getInitParameter(HTTPS_PORT); + if (param_https_port == null) { + msg = "The <param-name> '" + HTTPS_PORT + + "' </param-name> " + "MUST be specified in 'web.xml'!"; + CMS.debug(filterName + ": " + msg); + resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, msg); + return; + } + + param_proxy_http_port = config.getInitParameter(PROXY_HTTP_PORT); + param_proxy_port = config.getInitParameter(PROXY_PORT); + boolean bad_port = false; + + // If the scheme is "http", compare + // the request and param "http" ports; + // otherwise, if the scheme is "https", compare + // the request and param "https" ports + if (scheme.equals(HTTP_SCHEME)) { + if (!param_http_port.equals(request_port)) { + String uri = ((HttpServletRequest) request).getRequestURI(); + if (param_proxy_http_port != null) { + if (!param_proxy_http_port.equals(request_port)) { + msg = "Use HTTP port '" + param_http_port + + "' or proxy port '" + param_proxy_http_port + + "' instead of '" + request_port + + "' when performing " + HTTP_ROLE + " tasks!"; + bad_port = true; + } + } else { + msg = "Use HTTP port '" + param_http_port + + "' instead of '" + request_port + + "' when performing " + HTTP_ROLE + " tasks!"; + bad_port = true; + } + if (bad_port) { + CMS.debug(filterName + ": " + msg); + CMS.debug(filterName + ": uri is " + uri); + if ((param_active != null) && (param_active.equals("false"))) { + CMS.debug("Filter is disabled .. continuing"); + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg); + return; + } + } + } + } else if (scheme.equals(HTTPS_SCHEME)) { + if (!param_https_port.equals(request_port)) { + String uri = ((HttpServletRequest) request).getRequestURI(); + if (param_proxy_port != null) { + if (!param_proxy_port.equals(request_port)) { + msg = "Use HTTPS port '" + param_https_port + + "' or proxy port '" + param_proxy_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + } else { + msg = "Use HTTPS port '" + param_https_port + + "' instead of '" + request_port + + "' when performing " + HTTPS_ROLE + " tasks!"; + bad_port = true; + } + if (bad_port) { + CMS.debug(filterName + ": " + msg); + CMS.debug(filterName + ": uri is " + uri); + if ((param_active != null) && (param_active.equals("false"))) { + CMS.debug("Filter is disabled .. continuing"); + } else { + resp.sendError(HttpServletResponse.SC_NOT_FOUND, msg); + return; + } + } + } + } + + } + // CMS.debug("Exiting the EE filter"); + + chain.doFilter(request, response); + } + + public void destroy() { + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java b/base/common/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java new file mode 100644 index 000000000..59b01f26a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java @@ -0,0 +1,187 @@ +// --- 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.key; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.kra.IKeyService; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * A class representing a recoverKey servlet. This servlet + * shows key information and presents a list of text boxes + * so that recovery agents can type in their identifiers + * and passwords. + * + * @version $Revision$, $Date$ + */ +public class ConfirmRecoverBySerial extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 2221819191344494389L; + private final static String INFO = "recoverBySerial"; + private final static String TPL_FILE = + "confirmRecoverBySerial.template"; + + private final static String IN_SERIALNO = "serialNumber"; + private final static String OUT_SERIALNO = IN_SERIALNO; + private final static String OUT_OP = "op"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_M = "noOfRequiredAgents"; + private final static String OUT_ERROR = "errorDetails"; + + private IKeyRepository mKeyDB = null; + private IKeyService mRecoveryService = null; + private String mFormPath = null; + + /** + * Constructs ConfirmRecoverBySerial servlet. + */ + public ConfirmRecoverBySerial() { + super(); + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mRecoveryService = (IKeyService) mAuthority; + mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository(); + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP request. The format of this request is + * as follows: + * confirmRecoverBySerial? + * [serialNumber=<serialno>] + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + // Note that we should try to handle all the exceptions + // instead of passing it up back to the servlet + // framework. + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + authenticate(cmsReq); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + BigInteger seqNum = BigInteger.ZERO; + + try { + if (req.getParameter(IN_SERIALNO) != null) { + seqNum = new BigInteger(req.getParameter(IN_SERIALNO)); + } + + // make sure this page, which contains password + // information, is not cache. Too bad, this is + // only good for NS browser, not IE specifically. + resp.setHeader("pragma", "no-cache"); + + process(argSet, header, seqNum, req, resp, locale[0]); + } catch (NumberFormatException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + } + + /** + * Requests for a list of agent passwords. + */ + private void process(CMSTemplateParams argSet, + IArgBlock header, BigInteger seq, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + try { + header.addBigIntegerValue(OUT_SERIALNO, seq, 10); + header.addIntegerValue(OUT_M, + mRecoveryService.getNoOfRequiredAgents()); + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + + IKeyRecord rec = (IKeyRecord) mKeyDB.readKeyRecord(seq); + + KeyRecordParser.fillRecordIntoArg(rec, header); + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/DisplayBySerial.java b/base/common/src/com/netscape/cms/servlet/key/DisplayBySerial.java new file mode 100644 index 000000000..8876d9350 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/DisplayBySerial.java @@ -0,0 +1,194 @@ +// --- 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.key; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Display a specific Key Archival Request + * <P> + * + * @version $Revision$, $Date$ + */ +public class DisplayBySerial extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -537957487396615246L; + private final static String INFO = "displayBySerial"; + private final static String TPL_FILE = "displayBySerial.template"; + + private final static String IN_SERIALNO = "serialNumber"; + private final static String OUT_OP = "op"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_ERROR = "errorDetails"; + + private IKeyRepository mKeyDB = null; + private String mFormPath = null; + + /** + * Constructs displayBySerial servlet. + */ + public DisplayBySerial() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "displayBySerial.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); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository(); + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param serialNumber serial number of the key archival request + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + // Note that we should try to handle all the exceptions + // instead of passing it up back to the servlet + // framework. + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + BigInteger seqNum = BigInteger.ZERO; + + try { + if (req.getParameter(IN_SERIALNO) != null) { + seqNum = new BigInteger(req.getParameter(IN_SERIALNO)); + } + process(argSet, header, seqNum, req, resp, locale[0]); + } catch (NumberFormatException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Display information about a particular key. + */ + private void process(CMSTemplateParams argSet, + IArgBlock header, BigInteger seq, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + try { + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + IKeyRecord rec = (IKeyRecord) mKeyDB.readKeyRecord(seq); + + KeyRecordParser.fillRecordIntoArg(rec, header); + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java b/base/common/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java new file mode 100644 index 000000000..29cc2b3b3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java @@ -0,0 +1,213 @@ +// --- 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.key; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.kra.IKeyService; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Display a Specific Key Archival Request, and initiate + * key recovery process + * + * @version $Revision$, $Date$ + */ +public class DisplayBySerialForRecovery extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 6876016034084761827L; + private final static String INFO = "displayBySerial"; + private final static String TPL_FILE = "displayBySerialForRecovery.template"; + + private final static String IN_SERIALNO = "serialNumber"; + private final static String OUT_OP = "op"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_ERROR = "errorDetails"; + + private IKeyRepository mKeyDB = null; + private String mFormPath = null; + private IKeyService mService = null; + + /** + * Constructor + */ + public DisplayBySerialForRecovery() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "displayBySerialForRecovery.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); + mFormPath = "/agent/" + mAuthority.getId() + "/" + TPL_FILE; + mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository(); + mService = (IKeyService) mAuthority; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param serialNumber request ID of key archival request + * <li>http.param publicKeyData + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + // Note that we should try to handle all the exceptions + // instead of passing it up back to the servlet + // framework. + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + BigInteger seqNum = BigInteger.ZERO; + + try { + if (req.getParameter(IN_SERIALNO) != null) { + seqNum = new BigInteger(req.getParameter(IN_SERIALNO)); + } + process(argSet, header, + req.getParameter("publicKeyData"), + seqNum, req, resp, locale[0]); + } catch (NumberFormatException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } catch (Exception e) { + e.printStackTrace(); + System.out.println(e.toString()); + } + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + } + + /** + * Display information about a particular key. + */ + private synchronized void process(CMSTemplateParams argSet, + IArgBlock header, String publicKeyData, BigInteger seq, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + try { + header.addIntegerValue("noOfRequiredAgents", + mService.getNoOfRequiredAgents()); + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue("keySplitting", + CMS.getConfigStore().getString("kra.keySplitting")); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + if (publicKeyData != null) { + header.addStringValue("publicKeyData", + publicKeyData); + } + IKeyRecord rec = (IKeyRecord) mKeyDB.readKeyRecord(seq); + + KeyRecordParser.fillRecordIntoArg(rec, header); + + // recovery identifier + header.addStringValue("recoveryID", mService.getRecoveryID()); + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/DisplayTransport.java b/base/common/src/com/netscape/cms/servlet/key/DisplayTransport.java new file mode 100644 index 000000000..dd224cc8a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/DisplayTransport.java @@ -0,0 +1,125 @@ +// --- 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.key; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.security.ITransportKeyUnit; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve Transport Certificate used to + * wrap Private key Archival requests + * + * @version $Revision$, $Date$ + */ +public class DisplayTransport extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -6509083753395783705L; + private final static String INFO = "displayTransport"; + + /** + * Constructs displayTransport servlet. + */ + public DisplayTransport() { + super(); + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + try { + IKeyRecoveryAuthority kra = + (IKeyRecoveryAuthority) mAuthority; + ITransportKeyUnit tu = kra.getTransportKeyUnit(); + org.mozilla.jss.crypto.X509Certificate transportCert = + tu.getCertificate(); + + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("text/html"); + String content = ""; + + content += "<HTML><PRE>"; + String mime64 = + "-----BEGIN CERTIFICATE-----\n" + + CMS.BtoA(transportCert.getEncoded()) + + "-----END CERTIFICATE-----\n"; + + content += mime64; + content += "</PRE></HTML>"; + resp.setContentType("text/html"); + resp.getOutputStream().write(content.getBytes()); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/ExamineRecovery.java b/base/common/src/com/netscape/cms/servlet/key/ExamineRecovery.java new file mode 100644 index 000000000..cd440da08 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/ExamineRecovery.java @@ -0,0 +1,249 @@ +// --- 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.key; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Hashtable; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.kra.IKeyService; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * View the Key Recovery Request + * + * @version $Revision$, $Date$ + */ +public class ExamineRecovery extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -953282265332774966L; + private final static String INFO = "examineRecovery"; + private final static String TPL_FILE = "examineRecovery.template"; + + private final static String IN_SERIALNO = "serialNumber"; + private final static String IN_UID = "uid"; + private final static String IN_PWD = "pwd"; + private final static String IN_PASSWORD = "p12Password"; + private final static String IN_DELIVERY = "p12Delivery"; + private final static String IN_CERT = "cert"; + + private final static String OUT_OP = "op"; + private final static String OUT_SERIALNO = IN_SERIALNO; + private final static String OUT_RECOVERY_SUCCESS = "recoverySuccess"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_ERROR = "errorDetails"; + + private IKeyService mService = null; + private String mFormPath = null; + + /** + * Constructs EA servlet. + */ + public ExamineRecovery() { + super(); + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mService = (IKeyService) mAuthority; + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param recoveryID recovery request ID + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + EBaseException error = null; + + try { + process(argSet, header, + req.getParameter("recoveryID"), + req, resp, locale[0]); + } catch (EBaseException e) { + error = e; + } catch (Exception e) { + error = new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", e.toString())); + } + + /* + catch (NumberFormatException e) { + error = eBaseException( + + header.addStringValue(OUT_ERROR, + MessageFormatter.getLocalizedString( + locale[0], + BaseResources.class.getName(), + BaseResources.INTERNAL_ERROR_1, + e.toString())); + } + */ + + try { + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + ServletOutputStream out = resp.getOutputStream(); + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Recovers a key. The p12 will be protected by the password + * provided by the administrator. + */ + private void process(CMSTemplateParams argSet, + IArgBlock header, String recoveryID, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) + throws EBaseException { + try { + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + header.addStringValue("keySplitting", + CMS.getConfigStore().getString("kra.keySplitting")); + Hashtable<String, Object> params = mService.getRecoveryParams( + recoveryID); + + if (params == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_RECOVERY_TOKEN_FOUND_1", recoveryID)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_RECOVERY_TOKEN_FOUND", recoveryID)); + } + String keyID = (String) params.get("keyID"); + header.addStringValue("serialNumber", keyID); + header.addStringValue("recoveryID", recoveryID); + + IKeyRepository mKeyDB = + ((IKeyRecoveryAuthority) mAuthority).getKeyRepository(); + IKeyRecord rec = (IKeyRecord) mKeyDB.readKeyRecord(new + BigInteger(keyID)); + KeyRecordParser.fillRecordIntoArg(rec, header); + + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, "Error e " + e); + throw e; + } + + /* + catch (Exception e) { + header.addStringValue(OUT_ERROR, e.toString()); + } + */ + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/GetApprovalStatus.java b/base/common/src/com/netscape/cms/servlet/key/GetApprovalStatus.java new file mode 100644 index 000000000..55d79b1ab --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/GetApprovalStatus.java @@ -0,0 +1,235 @@ +// --- 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.key; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.security.Credential; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Check to see if a Key Recovery Request has been approved + * + * @version $Revision$, $Date$ + */ +public class GetApprovalStatus extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -8257339915430654983L; + private final static String INFO = "getApprovalStatus"; + private final static String TPL_FILE = "getApprovalStatus.template"; + private final static String TPL_FINISH = "finishRecovery.template"; + + private final static String IN_DELIVERY = "p12Delivery"; + + private final static String OUT_RECOVERY_SUCCESS = "recoverySuccess"; + private final static String OUT_ERROR = "errorDetails"; + private final static String OUT_STATUS = "status"; + + private com.netscape.certsrv.kra.IKeyService mService = null; + private String mFormPath = null; + + /** + * Constructs getApprovalStatus servlet. + */ + public GetApprovalStatus() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template files + * "getApprovalStatus.template" and "finishRecovery.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); + // mFormPath = "/"+authority.getId()+"/"+TPL_FILE; + mService = (com.netscape.certsrv.kra.IKeyService) mAuthority; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param recoveryID request ID to check + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + cmsReq.setStatus(CMSRequest.SUCCESS); + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + int rComplete = 0; + + // get status and populate argSet + try { + String recoveryID = req.getParameter("recoveryID"); + + header.addStringValue("recoveryID", recoveryID); + + Hashtable<String, Object> params = mService.getRecoveryParams(recoveryID); + + if (params == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_RECOVERY_TOKEN_FOUND_1", recoveryID)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_RECOVERY_TOKEN_FOUND", recoveryID)); + } + header.addStringValue("serialNumber", + (String) params.get("keyID")); + + int requiredNumber = mService.getNoOfRequiredAgents(); + + header.addIntegerValue("noOfRequiredAgents", requiredNumber); + + Vector<Credential> dc = ((IKeyRecoveryAuthority) mService).getAppAgents(recoveryID); + Enumeration<Credential> agents = dc.elements(); + + while (agents.hasMoreElements()) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("agentName", agents.nextElement().getIdentifier()); + argSet.addRepeatRecord(rarg); + } + if (dc.size() >= requiredNumber) { + // got all approval, return pk12 + byte pkcs12[] = ((IKeyRecoveryAuthority) mService).getPk12(recoveryID); + + if (pkcs12 != null) { + rComplete = 1; + header.addStringValue(OUT_STATUS, "complete"); + + /* + mService.destroyRecoveryParams(recoveryID); + try { + resp.setContentType("application/x-pkcs12"); + resp.getOutputStream().write(pkcs12); + return; + } catch (IOException e) { + header.addStringValue(OUT_ERROR, + MessageFormatter.getLocalizedString( + locale[0], + BaseResources.class.getName(), + BaseResources.INTERNAL_ERROR_1, + e.toString())); + } + */ + } else if (((IKeyRecoveryAuthority) mService).getError(recoveryID) != null) { + // error in recovery process + header.addStringValue(OUT_ERROR, + ((IKeyRecoveryAuthority) mService).getError(recoveryID)); + rComplete = 1; + } else { + // pk12 hasn't been created yet. + } + } + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale[0])); + rComplete = 1; + } + + try { + if (rComplete == 1) { + mFormPath = "/" + ((IAuthority) mService).getId() + "/" + TPL_FINISH; + } else { + mFormPath = "/" + ((IAuthority) mService).getId() + "/" + TPL_FILE; + } + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/GetAsyncPk12.java b/base/common/src/com/netscape/cms/servlet/key/GetAsyncPk12.java new file mode 100644 index 000000000..9d67cab8d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/GetAsyncPk12.java @@ -0,0 +1,266 @@ +// --- 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.key; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Get the recovered key in PKCS#12 format + * - for asynchronous key recovery only + * + */ +public class GetAsyncPk12 extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 6933634840339605800L; + + private final static String INFO = "getAsyncPk12"; + + private final static String TPL_FILE = "finishAsyncRecovery.template"; + + private final static String IN_PASSWORD = "p12Password"; + private final static String IN_PASSWORD_AGAIN = "p12PasswordAgain"; + private final static String OUT_RECOVERY_SUCCESS = "recoverySuccess"; + private final static String OUT_ERROR = "errorDetails"; + + private com.netscape.certsrv.kra.IKeyService mService = null; + private final static String OUT_STATUS = "status"; + + private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS_4"; + + private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE_4"; + + private String mFormPath = null; + + /** + * Constructs getAsyncPk12 servlet. + */ + public GetAsyncPk12() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "finishAsyncRecovery.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); + mFormPath = "/agent/" + mAuthority.getId() + "/" + TPL_FILE; + mService = (com.netscape.certsrv.kra.IKeyService) mAuthority; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param reqID request id for recovery + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + String auditMessage = null; + String agent = null; + String reqID = null; + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "download"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + // get status and populate argSet + try { + reqID = req.getParameter("reqID"); + header.addStringValue("reqID", reqID); + + // only the init DRM agent can get the pkcs12 + SessionContext sContext = SessionContext.getContext(); + + if (sContext != null) { + agent = (String) sContext.get(SessionContext.USER_ID); + } + + if (agent == null) { + CMS.debug("GetAsyncPk12::process() - agent is null!"); + throw new EBaseException("agent is null"); + } + + String initAgent = "undefined"; + initAgent = mService.getInitAgentAsyncKeyRecovery(reqID); + + if ((initAgent.equals("undefined")) || !agent.equals(initAgent)) { + log(ILogger.LL_SECURITY, + CMS.getLogMessage("CMSGW_INVALID_AGENT_ASYNC_3", + reqID, initAgent)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_AGENT_ASYNC", + reqID, initAgent)); + } + + // The async recovery request must be in "approved" state + // i.e. all required # of recovery agents approved + if (mService.isApprovedAsyncKeyRecovery(reqID) != true) { + CMS.debug("GetAsyncPk12::process() - # required recovery agents not met"); + throw new EBaseException("# required recovery agents not met"); + } + + String password = req.getParameter(IN_PASSWORD); + String passwordAgain = req.getParameter(IN_PASSWORD_AGAIN); + + if (password == null || password.equals("")) { + header.addStringValue(OUT_ERROR, "PKCS12 password not found"); + throw new EBaseException("PKCS12 password not found"); + } + if (passwordAgain == null || !passwordAgain.equals(password)) { + header.addStringValue(OUT_ERROR, "PKCS12 password not matched"); + throw new EBaseException("PKCS12 password not matched"); + } + + // got all approval, return pk12 + byte pkcs12[] = mService.doKeyRecovery(reqID, password); + + if (pkcs12 != null) { + try { + resp.setContentType("application/x-pkcs12"); + resp.getOutputStream().write(pkcs12); + mRenderResult = false; + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS, + agent, + ILogger.SUCCESS, + reqID, + ""); + + audit(auditMessage); + + return; + } catch (IOException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + } else if (((IKeyRecoveryAuthority) mService).getError(reqID) != null) { + // error in recovery process + header.addStringValue(OUT_ERROR, + ((IKeyRecoveryAuthority) mService).getError(reqID)); + } else { + // pk12 hasn't been created yet. Shouldn't get here + } + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale[0])); + } + + if ((agent != null) && (reqID != null)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE, + agent, + ILogger.FAILURE, + reqID, + ""); + + audit(auditMessage); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/GetPk12.java b/base/common/src/com/netscape/cms/servlet/key/GetPk12.java new file mode 100644 index 000000000..96fe7c85d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/GetPk12.java @@ -0,0 +1,260 @@ +// --- 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.key; + +import java.io.IOException; +import java.util.Hashtable; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Get the recovered key in PKCS#12 format + * + * @version $Revision$, $Date$ + */ +public class GetPk12 extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 8974964964333880697L; + + private final static String INFO = "getPk12"; + + private final static String TPL_FILE = "finishRecovery.template"; + + private final static String OUT_RECOVERY_SUCCESS = "recoverySuccess"; + private final static String OUT_ERROR = "errorDetails"; + + private com.netscape.certsrv.kra.IKeyService mService = null; + private final static String OUT_STATUS = "status"; + + private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS_4"; + + private final static String LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE_4"; + + private String mFormPath = null; + + /** + * Constructs getPk12 servlet. + */ + public GetPk12() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "finishRecovery.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); + mFormPath = "/agent/" + mAuthority.getId() + "/" + TPL_FILE; + mService = (com.netscape.certsrv.kra.IKeyService) mAuthority; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param recoveryID ID of request to recover + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + String auditMessage = null; + String recoveryID = null; + String agent = null; + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "download"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + // get status and populate argSet + try { + recoveryID = req.getParameter("recoveryID"); + + header.addStringValue("recoveryID", recoveryID); + + Hashtable<String, Object> params = mService.getRecoveryParams(recoveryID); + + if (params == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_RECOVERY_TOKEN_FOUND_1", recoveryID)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_RECOVERY_TOKEN_FOUND", recoveryID)); + } + + // only the init DRM agent can get the pkcs12 + SessionContext sContext = SessionContext.getContext(); + if (sContext != null) { + agent = (String) sContext.get(SessionContext.USER_ID); + } + + if (agent == null) { + CMS.debug("GetPk12::process() - agent is null!"); + throw new EBaseException("agent is null"); + } + + String initAgent = (String) params.get("agent"); + + if (!agent.equals(initAgent)) { + log(ILogger.LL_SECURITY, + + CMS.getLogMessage("CMSGW_INVALID_AGENT_3", + recoveryID, + initAgent)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_AGENT", + agent, initAgent, recoveryID)); + } + + header.addStringValue("serialNumber", + (String) params.get("keyID")); + + // got all approval, return pk12 + byte pkcs12[] = ((IKeyRecoveryAuthority) mService).getPk12(recoveryID); + + if (pkcs12 != null) { + mService.destroyRecoveryParams(recoveryID); + try { + resp.setContentType("application/x-pkcs12"); + resp.getOutputStream().write(pkcs12); + mRenderResult = false; + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_SUCCESS, + agent, + ILogger.SUCCESS, + recoveryID, + ""); + + audit(auditMessage); + + return; + } catch (IOException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + } else if (((IKeyRecoveryAuthority) mService).getError(recoveryID) != null) { + // error in recovery process + header.addStringValue(OUT_ERROR, + ((IKeyRecoveryAuthority) mService).getError(recoveryID)); + } else { + // pk12 hasn't been created yet. Shouldn't get here + } + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale[0])); + } + + if ((agent != null) && (recoveryID != null)) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PRIVATE_KEY_EXPORT_REQUEST_PROCESSED_FAILURE, + agent, + ILogger.FAILURE, + recoveryID, + ""); + + audit(auditMessage); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/GrantAsyncRecovery.java b/base/common/src/com/netscape/cms/servlet/key/GrantAsyncRecovery.java new file mode 100644 index 000000000..7c0c0cb1c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/GrantAsyncRecovery.java @@ -0,0 +1,280 @@ +// --- 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) 2010 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.key; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.kra.IKeyService; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Approve an asynchronous key recovery request + * + */ +public class GrantAsyncRecovery extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -4200111795169532676L; + private final static String INFO = "grantAsyncRecovery"; + private final static String TPL_FILE = "grantAsyncRecovery.template"; + + private final static String IN_SERIALNO = "serialNumber"; + private final static String IN_REQ_ID = "reqID"; + private final static String IN_UID = "uid"; + private final static String IN_CERT = "cert"; + + private final static String OUT_OP = "op"; + private final static String OUT_SERIALNO = IN_SERIALNO; + private final static String OUT_RECOVERY_SUCCESS = "recoverySuccess"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_ERROR = "errorDetails"; + + private IKeyService mService = null; + private String mFormPath = null; + + private final static String LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN = + "LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN_4"; + + /** + * Constructs EA servlet. + */ + public GrantAsyncRecovery() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * 'grantAsyncRecovery.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); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mService = (IKeyService) mAuthority; + + mTemplates.remove(CMSRequest.SUCCESS); + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param reqID request ID of the request to approve + * <li>http.param agentID User ID of the agent approving the request + * + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + CMS.debug("GrantAsyncRecovery: process() begins"); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "recover"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + String agentID = authToken.getInString("uid"); + CMS.debug("GrantAsyncRecovery: process() agent uid=" + agentID); + CMS.debug("GrantAsyncRecovery: process() request id=" + req.getParameter("reqID")); + try { + process(argSet, header, + req.getParameter("reqID"), + agentID, + req, resp, locale[0]); + } catch (NumberFormatException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + } + + /** + * Update agent approval list + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN used whenever DRM agents login as recovery agents + * to approve key recovery requests + * </ul> + * + * @param argSet CMS template parameters + * @param header argument block + * @param reqID string containing the recovery request ID + * @param agentID string containing the agent ID + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param locale the system locale + */ + private void process(CMSTemplateParams argSet, + IArgBlock header, String reqID, + String agentID, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequestID = reqID; + String auditAgentID = agentID; + + // "normalize" the "reqID" + if (auditRequestID != null) { + auditRequestID = auditRequestID.trim(); + + if (auditRequestID.equals("")) { + auditRequestID = ILogger.UNIDENTIFIED; + } + } else { + auditRequestID = ILogger.UNIDENTIFIED; + } + + // "normalize" the "auditAgentID" + if (auditAgentID != null) { + auditAgentID = auditAgentID.trim(); + + if (auditAgentID.equals("")) { + auditAgentID = ILogger.UNIDENTIFIED; + } + } else { + auditAgentID = ILogger.UNIDENTIFIED; + } + + try { + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + + // update approving agent list + mService.addAgentAsyncKeyRecovery(reqID, agentID); + + header.addStringValue("requestID", reqID); + header.addStringValue("agentID", agentID); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN, + auditSubjectID, + ILogger.SUCCESS, + auditRequestID, + auditAgentID); + + audit(auditMessage); + + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN, + auditSubjectID, + ILogger.FAILURE, + auditRequestID, + auditAgentID); + + audit(auditMessage); + } catch (Exception e) { + header.addStringValue(OUT_ERROR, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN, + auditSubjectID, + ILogger.FAILURE, + auditRequestID, + auditAgentID); + + audit(auditMessage); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/GrantRecovery.java b/base/common/src/com/netscape/cms/servlet/key/GrantRecovery.java new file mode 100644 index 000000000..02aacc31c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/GrantRecovery.java @@ -0,0 +1,308 @@ +// --- 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.key; + +import java.io.IOException; +import java.util.Hashtable; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.kra.IKeyService; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Approve a key recovery request + * + * @version $Revision$, $Date$ + */ +public class GrantRecovery extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 991970686415492L; + private final static String INFO = "grantRecovery"; + private final static String TPL_FILE = "grantRecovery.template"; + + private final static String IN_SERIALNO = "serialNumber"; + private final static String IN_UID = "uid"; + private final static String IN_PWD = "pwd"; + private final static String IN_PASSWORD = "p12Password"; + private final static String IN_DELIVERY = "p12Delivery"; + private final static String IN_CERT = "cert"; + + private final static String OUT_OP = "op"; + private final static String OUT_SERIALNO = IN_SERIALNO; + private final static String OUT_RECOVERY_SUCCESS = "recoverySuccess"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_ERROR = "errorDetails"; + + private IKeyService mService = null; + private String mFormPath = null; + + private final static String LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN = + "LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN_4"; + + /** + * Constructs EA servlet. + */ + public GrantRecovery() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * 'grantRecovery.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); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mService = (IKeyService) mAuthority; + + mTemplates.remove(CMSRequest.SUCCESS); + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param recoveryID ID of the request to approve + * <li>http.param agentID User ID of the agent approving the request + * <li>http.param agentPWD Password of the agent approving the request + * + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "recover"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + String agentID = authToken.getInString("uid"); + if (CMS.getConfigStore().getBoolean("kra.keySplitting")) { + agentID = req.getParameter("agentID"); + } + try { + process(argSet, header, + req.getParameter("recoveryID"), + agentID, + req.getParameter("agentPWD"), + req, resp, locale[0]); + } catch (NumberFormatException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + } + + /** + * Recovers a key. The p12 will be protected by the password + * provided by the administrator. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN used whenever DRM agents login as recovery agents + * to approve key recovery requests + * </ul> + * + * @param argSet CMS template parameters + * @param header argument block + * @param recoveryID string containing the recovery ID + * @param agentID string containing the agent ID + * @param agentPWD string containing the agent password + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param locale the system locale + */ + private void process(CMSTemplateParams argSet, + IArgBlock header, String recoveryID, + String agentID, String agentPWD, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRecoveryID = recoveryID; + String auditAgentID = agentID; + + // "normalize" the "auditRecoveryID" + if (auditRecoveryID != null) { + auditRecoveryID = auditRecoveryID.trim(); + + if (auditRecoveryID.equals("")) { + auditRecoveryID = ILogger.UNIDENTIFIED; + } + } else { + auditRecoveryID = ILogger.UNIDENTIFIED; + } + + // "normalize" the "auditAgentID" + if (auditAgentID != null) { + auditAgentID = auditAgentID.trim(); + + if (auditAgentID.equals("")) { + auditAgentID = ILogger.UNIDENTIFIED; + } + } else { + auditAgentID = ILogger.UNIDENTIFIED; + } + + try { + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + + Hashtable<String, Object> h = mService.getRecoveryParams(recoveryID); + + if (h == null) { + header.addStringValue(OUT_ERROR, + "No such token found"); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN, + auditSubjectID, + ILogger.FAILURE, + auditRecoveryID, + auditAgentID); + + audit(auditMessage); + + return; + } + header.addStringValue("serialNumber", + (String) h.get("keyID")); + + mService.addDistributedCredential(recoveryID, agentID, agentPWD); + header.addStringValue("agentID", + agentID); + header.addStringValue("recoveryID", + recoveryID); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN, + auditSubjectID, + ILogger.SUCCESS, + auditRecoveryID, + auditAgentID); + + audit(auditMessage); + + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN, + auditSubjectID, + ILogger.FAILURE, + auditRecoveryID, + auditAgentID); + + audit(auditMessage); + } catch (Exception e) { + header.addStringValue(OUT_ERROR, e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_KEY_RECOVERY_AGENT_LOGIN, + auditSubjectID, + ILogger.FAILURE, + auditRecoveryID, + auditAgentID); + + audit(auditMessage); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/KeyRecordParser.java b/base/common/src/com/netscape/cms/servlet/key/KeyRecordParser.java new file mode 100644 index 000000000..aeee624c0 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/KeyRecordParser.java @@ -0,0 +1,87 @@ +// --- 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.key; + +import java.util.Date; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IPrettyPrintFormat; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; + +/** + * Output a 'pretty print' of a Key Archival record + * + * @version $Revision$, $Date$ + */ +public class KeyRecordParser { + + public final static String OUT_STATE = "state"; + public final static String OUT_OWNER_NAME = "ownerName"; + public final static String OUT_SERIALNO = "serialNumber"; + public final static String OUT_KEY_ALGORITHM = "keyAlgorithm"; + public final static String OUT_PUBLIC_KEY = "publicKey"; + public final static String OUT_KEY_LEN = "keyLength"; + public final static String OUT_ARCHIVED_BY = "archivedBy"; + public final static String OUT_ARCHIVED_ON = "archivedOn"; + public final static String OUT_RECOVERED_BY = "recoveredBy"; + public final static String OUT_RECOVERED_ON = "recoveredOn"; + + /** + * Fills key record into argument block. + */ + public static void fillRecordIntoArg(IKeyRecord rec, IArgBlock rarg) + throws EBaseException { + if (rec == null) + return; + rarg.addStringValue(OUT_STATE, + rec.getState().toString()); + rarg.addStringValue(OUT_OWNER_NAME, + rec.getOwnerName()); + rarg.addBigIntegerValue(OUT_SERIALNO, + rec.getSerialNumber(), 10); + rarg.addStringValue(OUT_KEY_ALGORITHM, + rec.getAlgorithm()); + // Possible Enhancement: sun's BASE64Encode is not + // fast. We may may to have our native implmenetation. + IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":"); + + rarg.addStringValue(OUT_PUBLIC_KEY, + pp.toHexString(rec.getPublicKeyData(), 0, 20)); + Integer keySize = rec.getKeySize(); + + if (keySize == null) { + rarg.addIntegerValue(OUT_KEY_LEN, 512); + } else { + rarg.addIntegerValue(OUT_KEY_LEN, keySize.intValue()); + } + rarg.addStringValue(OUT_ARCHIVED_BY, + rec.getArchivedBy()); + rarg.addLongValue(OUT_ARCHIVED_ON, + rec.getCreateTime().getTime() / 1000); + Date dateOfRevocation[] = rec.getDateOfRevocation(); + + if (dateOfRevocation != null) { + rarg.addStringValue(OUT_RECOVERED_BY, + "null"); + rarg.addStringValue(OUT_RECOVERED_ON, + "null"); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/KeyResource.java b/base/common/src/com/netscape/cms/servlet/key/KeyResource.java new file mode 100644 index 000000000..a47c46d86 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/KeyResource.java @@ -0,0 +1,33 @@ +package com.netscape.cms.servlet.key; + +import javax.ws.rs.Consumes; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; + +import com.netscape.cms.servlet.key.model.KeyData; +import com.netscape.cms.servlet.request.model.RecoveryRequestData; + +@Path("/key") +public interface KeyResource { + + /** + * Used to retrieve a key + * @param data + * @return + */ + @POST + @Path("retrieve") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyData retrieveKey(RecoveryRequestData data); + + // retrieval - used to test integration with a browser + @POST + @Path("retrieve") + @Produces(MediaType.TEXT_XML) + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED}) + public KeyData retrieveKey(MultivaluedMap<String, String> form); +} diff --git a/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java b/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java new file mode 100644 index 000000000..79e6ccfdb --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/KeyResourceService.java @@ -0,0 +1,129 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.key; + + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.key.model.KeyDAO; +import com.netscape.cms.servlet.key.model.KeyData; +import com.netscape.cms.servlet.request.model.KeyRequestDAO; +import com.netscape.cms.servlet.request.model.KeyRequestInfo; +import com.netscape.cms.servlet.request.model.RecoveryRequestData; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.keydb.KeyId; + +/** + * @author alee + * + */ +public class KeyResourceService extends CMSResourceService implements KeyResource{ + + @Context + UriInfo uriInfo; + + /** + * Used to retrieve a key + * @param data + * @return + */ + public KeyData retrieveKey(RecoveryRequestData data) { + // auth and authz + KeyId keyId = validateRequest(data); + KeyDAO dao = new KeyDAO(); + KeyData keyData; + try { + keyData = dao.getKey(keyId, data); + } catch (EBaseException e) { + // log error + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + if (keyData == null) { + // no key record + throw new WebApplicationException(Response.Status.GONE); + } + return keyData; + } + + // retrieval - used to test integration with a browser + public KeyData retrieveKey(MultivaluedMap<String, String> form) { + RecoveryRequestData data = new RecoveryRequestData(form); + return retrieveKey(data); + } + + private KeyId validateRequest(RecoveryRequestData data) { + + // confirm request exists + RequestId reqId = data.getRequestId(); + if (reqId == null) { + // log error + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + + // confirm that at least one wrapping method exists + // There must be at least the wrapped session key method. + if ((data.getTransWrappedSessionKey() == null)) { + // log error + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + + KeyRequestDAO reqDAO = new KeyRequestDAO(); + KeyRequestInfo reqInfo; + try { + reqInfo = reqDAO.getRequest(reqId, uriInfo); + } catch (EBaseException e1) { + // failed to get request + e1.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + if (reqInfo == null) { + // request not found + throw new WebApplicationException(Response.Status.GONE); + } + + //confirm request is of the right type + String type = reqInfo.getRequestType(); + if (!type.equals(IRequest.SECURITY_DATA_RECOVERY_REQUEST)) { + // log error + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + + //confirm that agent is originator of request, else throw 401 + // TO-DO + + // confirm request is in approved state + String status = reqInfo.getRequestStatus(); + if (!status.equals(RequestStatus.APPROVED.toString())) { + // log error + throw new WebApplicationException(Response.Status.UNAUTHORIZED); + } + + return reqInfo.getKeyId(); + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/key/KeysResource.java b/base/common/src/com/netscape/cms/servlet/key/KeysResource.java new file mode 100644 index 000000000..c93ffa4c9 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/KeysResource.java @@ -0,0 +1,23 @@ +package com.netscape.cms.servlet.key; + +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import com.netscape.cms.servlet.key.model.KeyDataInfos; + +@Path("/keys") +public interface KeysResource { + public static final int DEFAULT_MAXTIME = 10; + public static final int DEFAULT_MAXRESULTS = 100; + + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + public KeyDataInfos listKeys(@QueryParam("clientID") String clientID, + @QueryParam("status") String status, + @DefaultValue(""+DEFAULT_MAXRESULTS) @QueryParam("maxResults") int maxResults, + @DefaultValue(""+DEFAULT_MAXTIME) @QueryParam("maxTime") int maxTime); + +} diff --git a/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java b/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java new file mode 100644 index 000000000..a7876a6c6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/KeysResourceService.java @@ -0,0 +1,91 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +/** + * + */ +package com.netscape.cms.servlet.key; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.key.model.KeyDAO; +import com.netscape.cms.servlet.key.model.KeyDataInfos; +import com.netscape.cmsutil.ldap.LDAPUtil; + +/** + * @author alee + * + */ +public class KeysResourceService extends CMSResourceService implements KeysResource { + + @Context + UriInfo uriInfo; + + /** + * Used to generate list of key infos based on the search parameters + */ + public KeyDataInfos listKeys(String clientID, String status, int maxResults, int maxTime) { + // auth and authz + + // get ldap filter + String filter = createSearchFilter(status, clientID); + CMS.debug("listKeys: filter is " + filter); + + KeyDAO dao = new KeyDAO(); + KeyDataInfos infos; + try { + infos = dao.listKeys(filter, maxResults, maxTime, uriInfo); + } catch (EBaseException e) { + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return infos; + } + + private String createSearchFilter(String status, String clientID) { + String filter = ""; + int matches = 0; + + if ((status == null) && (clientID == null)) { + filter = "(serialno=*)"; + return filter; + } + + if (status != null) { + filter += "(status=" + LDAPUtil.escape(status) + ")"; + matches ++; + } + + if (clientID != null) { + filter += "(clientID=" + LDAPUtil.escape(clientID) + ")"; + matches ++; + } + + if (matches > 1) { + filter = "(&" + filter + ")"; + } + + return filter; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/key/RecoverBySerial.java b/base/common/src/com/netscape/cms/servlet/key/RecoverBySerial.java new file mode 100644 index 000000000..28ff30803 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/RecoverBySerial.java @@ -0,0 +1,529 @@ +// --- 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.key; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +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.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.security.Credential; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Cert; + +/** + * A class representing a recoverBySerial servlet. + * + * @version $Revision$, $Date$ + */ +public class RecoverBySerial extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -4544485601409309840L; + private final static String INFO = "recoverBySerial"; + private final static String TPL_FILE = "recoverBySerial.template"; + + private final static String IN_SERIALNO = "serialNumber"; + private final static String IN_UID = "uid"; + private final static String IN_PWD = "pwd"; + private final static String IN_PASSWORD = "p12Password"; + private final static String IN_PASSWORD_AGAIN = "p12PasswordAgain"; + private final static String IN_DELIVERY = "p12Delivery"; + private final static String IN_CERT = "cert"; + private final static String IN_NICKNAME = "nickname"; + + private final static String OUT_OP = "op"; + private final static String OUT_SERIALNO = IN_SERIALNO; + private final static String OUT_RECOVERY_SUCCESS = "recoverySuccess"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_ERROR = "errorDetails"; + + private final static String SCHEME = "scheme"; + private final static String HOST = "host"; + private final static String PORT = "port"; + + private com.netscape.certsrv.kra.IKeyService mService = null; + private String mFormPath = null; + + /** + * Constructs EA servlet. + */ + public RecoverBySerial() { + super(); + } + + /** + * Initializes the servlet. + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mService = (com.netscape.certsrv.kra.IKeyService) mAuthority; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Serves HTTP request. The format of this request is as follows: + * recoverBySerial? + * [serialNumber=<number>] + * [uid#=<uid>] + * [pwd#=<password>] + * [localAgents=yes|null] + * [recoveryID=recoveryID] + * [pkcs12Password=<password of pkcs12>] + * [pkcs12PasswordAgain=<password of pkcs12>] + * [pkcs12Delivery=<delivery mechanism for pkcs12>] + * [cert=<encryption certificate>] + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "recover"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + // set host name and port. + HttpServletRequest httpReq = cmsReq.getHttpReq(); + String host = httpReq.getServerName(); + int port = httpReq.getServerPort(); + String scheme = httpReq.getScheme(); + + fixed.set(HOST, host); + fixed.set(PORT, Integer.valueOf(port)); + fixed.set(SCHEME, scheme); + + SessionContext ctx = null; + + try { + String initAsyncRecovery = req.getParameter("initAsyncRecovery"); + + // this information is needed within the server for + // various signed audit log messages to report + ctx = SessionContext.getContext(); + + /* + When Recovery is first initiated, if it is in asynch mode, + no pkcs#12 password is needed. + The initiating agent uid will be recorded in the recovery + request. + Later, as approving agents submit their approvals, they will + also be listed in the request. + */ + if ((initAsyncRecovery != null) && + initAsyncRecovery.equalsIgnoreCase("ON")) { + process(form, argSet, header, + req.getParameter(IN_SERIALNO), + req.getParameter(IN_CERT), + req, resp, locale[0]); + + int requiredNumber = mService.getNoOfRequiredAgents(); + header.addIntegerValue("noOfRequiredAgents", requiredNumber); + } else { + String recoveryID = req.getParameter("recoveryID"); + + if (recoveryID != null && !recoveryID.equals("")) { + ctx.put(SessionContext.RECOVERY_ID, + req.getParameter("recoveryID")); + } + byte pkcs12[] = process(form, argSet, header, + req.getParameter(IN_SERIALNO), + req.getParameter("localAgents"), + req.getParameter(IN_PASSWORD), + req.getParameter(IN_PASSWORD_AGAIN), + req.getParameter(IN_CERT), + req.getParameter(IN_DELIVERY), + req.getParameter(IN_NICKNAME), + req, resp, locale[0]); + + if (pkcs12 != null) { + //resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("application/x-pkcs12"); + //resp.setContentLength(pkcs12.length); + resp.getOutputStream().write(pkcs12); + mRenderResult = false; + return; + } + } + } catch (NumberFormatException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } catch (IOException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } finally { + SessionContext.releaseContext(); + } + + // return status page + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + cmsReq.setStatus(CMSRequest.SUCCESS); + } + + /** + * Async Key Recovery - request initiation + */ + private void process(CMSTemplate form, CMSTemplateParams argSet, + IArgBlock header, String seq, String cert, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + + // seq is the key id + if (seq == null) { + header.addStringValue(OUT_ERROR, "sequence number not found"); + return; + } + X509CertImpl x509cert = null; + + if (cert == null || cert.trim().length() == 0) { + header.addStringValue(OUT_ERROR, "certificate not found"); + return; + } else { + try { + x509cert = Cert.mapCert(cert); + } catch (IOException e) { + header.addStringValue(OUT_ERROR, e.toString()); + } + } + if (x509cert == null) { + header.addStringValue(OUT_ERROR, "invalid X.509 certificate"); + return; + } + + SessionContext sContext = SessionContext.getContext(); + + try { + String reqID = mService.initAsyncKeyRecovery( + new BigInteger(seq), x509cert, + (String) sContext.get(SessionContext.USER_ID)); + header.addStringValue(OUT_SERIALNO, req.getParameter(IN_SERIALNO)); + header.addStringValue("requestID", reqID); + } catch (EBaseException e) { + String error = + "Failed to recover key for key id " + + seq + ".\nException: " + e.toString(); + + CMS.getLogger().log(ILogger.EV_SYSTEM, + ILogger.S_KRA, ILogger.LL_FAILURE, error); + try { + ((IKeyRecoveryAuthority) mService).createError(seq, error); + } catch (EBaseException eb) { + CMS.getLogger().log(ILogger.EV_SYSTEM, + ILogger.S_KRA, ILogger.LL_FAILURE, eb.toString()); + } + } + return; + } + + /** + * Recovers a key. The p12 will be protected by the password + * provided by the administrator. + */ + private byte[] process(CMSTemplate form, CMSTemplateParams argSet, + IArgBlock header, String seq, String localAgents, + String password, String passwordAgain, + String cert, String delivery, String nickname, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + if (seq == null) { + header.addStringValue(OUT_ERROR, "sequence number not found"); + return null; + } + if (password == null || password.equals("")) { + header.addStringValue(OUT_ERROR, "PKCS12 password not found"); + return null; + } + if (passwordAgain == null || !passwordAgain.equals(password)) { + header.addStringValue(OUT_ERROR, "PKCS12 password not matched"); + return null; + } + X509CertImpl x509cert = null; + + if (cert == null || cert.trim().length() == 0) { + // perform recovery + header.addStringValue(OUT_ERROR, "certificate not found"); + return null; + } else { + try { + x509cert = Cert.mapCert(cert); + } catch (IOException e) { + header.addStringValue(OUT_ERROR, e.toString()); + } + } + if (x509cert == null) { + header.addStringValue(OUT_ERROR, "invalid X.509 certificate"); + return null; + } + try { + Credential creds[] = null; + + SessionContext sContext = SessionContext.getContext(); + String agent = null; + + if (sContext != null) { + agent = (String) sContext.get(SessionContext.USER_ID); + } + if (CMS.getConfigStore().getBoolean("kra.keySplitting")) { + if (localAgents == null) { + String recoveryID = req.getParameter("recoveryID"); + + if (recoveryID == null || recoveryID.equals("")) { + header.addStringValue(OUT_ERROR, "No recovery ID specified"); + return null; + } + Hashtable<String, Object> params = mService.createRecoveryParams(recoveryID); + + params.put("keyID", req.getParameter(IN_SERIALNO)); + + header.addStringValue("recoveryID", recoveryID); + + params.put("agent", agent); + + // new thread to wait for pk12 + Thread waitThread = new WaitApprovalThread(recoveryID, + seq, password, x509cert, delivery, nickname, + SessionContext.getContext()); + + waitThread.start(); + return null; + } else { + Vector<Credential> v = new Vector<Credential>(); + + for (int i = 0; i < mService.getNoOfRequiredAgents(); i++) { + String uid = req.getParameter(IN_UID + i); + String pwd = req.getParameter(IN_PWD + i); + + if (uid != null && pwd != null && !uid.equals("") && + !pwd.equals("")) { + v.addElement(new Credential(uid, pwd)); + } else { + header.addStringValue(OUT_ERROR, "Uid(s) or password(s) are not provided"); + return null; + } + } + if (v.size() != mService.getNoOfRequiredAgents()) { + header.addStringValue(OUT_ERROR, "Uid(s) or password(s) are not provided"); + return null; + } + creds = new Credential[v.size()]; + v.copyInto(creds); + } + + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addBigIntegerValue(OUT_SERIALNO, + new BigInteger(seq), 10); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + byte pkcs12[] = mService.doKeyRecovery( + new BigInteger(seq), + creds, password, x509cert, + delivery, nickname, agent); + + return pkcs12; + } else { + String recoveryID = req.getParameter("recoveryID"); + + if (recoveryID == null || recoveryID.equals("")) { + header.addStringValue(OUT_ERROR, "No recovery ID specified"); + return null; + } + Hashtable<String, Object> params = mService.createRecoveryParams(recoveryID); + + params.put("keyID", req.getParameter(IN_SERIALNO)); + + header.addStringValue("recoveryID", recoveryID); + + params.put("agent", agent); + + // new thread to wait for pk12 + Thread waitThread = new WaitApprovalThread(recoveryID, + seq, password, x509cert, delivery, nickname, + SessionContext.getContext()); + + waitThread.start(); + return null; + } + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } catch (Exception e) { + header.addStringValue(OUT_ERROR, e.toString()); + } + return null; + } + + /** + * Wait approval thread. Wait for recovery agents' approval + * exit when required number of approval received + */ + final class WaitApprovalThread extends Thread { + String theRecoveryID = null; + String theSeq = null; + String thePassword = null; + X509CertImpl theCert = null; + String theDelivery = null; + String theNickname = null; + SessionContext theSc = null; + + /** + * Wait approval thread constructor including thread name + */ + public WaitApprovalThread(String recoveryID, String seq, + String password, X509CertImpl cert, + String delivery, String nickname, SessionContext sc) { + super(); + super.setName("waitApproval." + recoveryID + "-" + + (Thread.activeCount() + 1)); + theRecoveryID = recoveryID; + theSeq = seq; + thePassword = password; + theCert = cert; + theDelivery = delivery; + theNickname = nickname; + theSc = sc; + } + + public void run() { + SessionContext.setContext(theSc); + Credential creds[] = null; + + try { + creds = mService.getDistributedCredentials(theRecoveryID); + } catch (EBaseException e) { + String error = + "Failed to get required approvals for recovery id " + + theRecoveryID + ".\nException: " + e.toString(); + + CMS.getLogger().log(ILogger.EV_SYSTEM, + ILogger.S_KRA, ILogger.LL_FAILURE, error); + try { + ((IKeyRecoveryAuthority) mService).createError(theRecoveryID, error); + } catch (EBaseException eb) { + CMS.getLogger().log(ILogger.EV_SYSTEM, + ILogger.S_KRA, ILogger.LL_FAILURE, eb.toString()); + } + return; + } + + SessionContext sContext = SessionContext.getContext(); + + try { + byte pkcs12[] = mService.doKeyRecovery( + new BigInteger(theSeq), + creds, thePassword, theCert, + theDelivery, theNickname, + (String) sContext.get(SessionContext.USER_ID)); + + ((IKeyRecoveryAuthority) mService).createPk12(theRecoveryID, pkcs12); + } catch (EBaseException e) { + String error = + "Failed to recover key for recovery id " + + theRecoveryID + ".\nException: " + e.toString(); + + CMS.getLogger().log(ILogger.EV_SYSTEM, + ILogger.S_KRA, ILogger.LL_FAILURE, error); + try { + ((IKeyRecoveryAuthority) mService).createError(theRecoveryID, error); + } catch (EBaseException eb) { + CMS.getLogger().log(ILogger.EV_SYSTEM, + ILogger.S_KRA, ILogger.LL_FAILURE, eb.toString()); + } + } + return; + } + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/key/SrchKey.java b/base/common/src/com/netscape/cms/servlet/key/SrchKey.java new file mode 100644 index 000000000..bff14e9f2 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/SrchKey.java @@ -0,0 +1,297 @@ +// --- 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.key; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X500Name; + +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.base.IArgBlock; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve archived keys matching search criteria + * + * @version $Revision$, $Date$ + */ +public class SrchKey extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -6404955402865756665L; + private final static String TPL_FILE = "srchKey.template"; + private final static String INFO = "srchKey"; + private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReturns"; + + // input parameters + private final static String IN_MAXCOUNT = "maxCount"; + private final static String IN_FILTER = "queryFilter"; + private final static String IN_SENTINEL = "querySentinel"; + + // output parameters + private final static String OUT_FILTER = IN_FILTER; + private final static String OUT_MAXCOUNT = IN_MAXCOUNT; + private final static String OUT_SENTINEL = IN_SENTINEL; + private final static String OUT_OP = "op"; + private final static String OUT_ERROR = "errorDetails"; + private final static String OUT_ARCHIVER = "archiverName"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_TOTAL_COUNT = "totalRecordCount"; + private final static String OUT_TEMPLATE = "templateName"; + + private IKeyRepository mKeyDB = null; + private X500Name mAuthName = null; + private String mFormPath = null; + private int mMaxReturns = 100; + private int mTimeLimits = 30; /* in seconds */ + + /** + * Constructs query key servlet. + */ + public SrchKey() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "srchKey.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); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + /* maxReturns doesn't seem to do anything useful in this + servlet!!! */ + try { + String tmp = + sc.getInitParameter(PROP_MAX_SEARCH_RETURNS); + + if (tmp == null) + mMaxReturns = 100; + else + mMaxReturns = Integer.parseInt(tmp); + } catch (Exception e) { + // do nothing + } + + mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository(); + mAuthName = ((IKeyRecoveryAuthority) mAuthority).getX500Name(); + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + /* Server-Side time limit */ + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param maxCount maximum number of matches to show in result + * <li>http.param maxResults maximum number of matches to run in ldapsearch + * <li>http.param queryFilter ldap-style filter to search with + * <li>http.param querySentinel ID of first request to show + * <li>http.param timeLimit number of seconds to limit ldap search to + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + // process query if authentication is successful + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + int maxCount = -1; + int sentinel = 0; + int maxResults = -1; + int timeLimit = -1; + + try { + if (req.getParameter(IN_MAXCOUNT) != null) { + maxCount = Integer.parseInt( + req.getParameter(IN_MAXCOUNT)); + } + if (req.getParameter(IN_SENTINEL) != null) { + sentinel = Integer.parseInt( + req.getParameter(IN_SENTINEL)); + } + String maxResultsStr = req.getParameter("maxResults"); + + if (maxResultsStr != null && maxResultsStr.length() > 0) + maxResults = Integer.parseInt(maxResultsStr); + String timeLimitStr = req.getParameter("timeLimit"); + + if (timeLimitStr != null && timeLimitStr.length() > 0) + timeLimit = Integer.parseInt(timeLimitStr); + process(argSet, header, ctx, maxCount, maxResults, + timeLimit, sentinel, + req.getParameter(IN_FILTER), req, resp, locale[0]); + } catch (NumberFormatException e) { + header.addStringValue(OUT_ERROR, + CMS.getUserMessage(locale[0], "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + } + + /** + * Process the key search. + */ + private void process(CMSTemplateParams argSet, + IArgBlock header, IArgBlock ctx, + int maxCount, int maxResults, int timeLimit, int sentinel, String filter, + HttpServletRequest req, HttpServletResponse resp, Locale locale) { + + try { + // Fill header + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue(OUT_ARCHIVER, + mAuthName.toString()); + // STRANGE: IE does not like the following: + // header.addStringValue(OUT_SERVICE_URL, + // req.getRequestURI()); + // XXX + header.addStringValue(OUT_SERVICE_URL, + "/kra?"); + header.addStringValue(OUT_TEMPLATE, + TPL_FILE); + header.addStringValue(OUT_FILTER, + filter); + + if (timeLimit == -1 || timeLimit > mTimeLimits) { + CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits); + timeLimit = mTimeLimits; + } + CMS.debug("Start searching ... timelimit=" + timeLimit); + Enumeration<IKeyRecord> e = mKeyDB.searchKeys(filter, + maxResults, timeLimit); + int count = 0; + + if (e == null) { + header.addStringValue(OUT_SENTINEL, + null); + } else { + while (e.hasMoreElements()) { + IKeyRecord rec = e.nextElement(); + // rec is null when we specify maxResults + // DS will return an err=4, which triggers + // a LDAPException.SIZE_LIMIT_ExCEEDED + // in DSSearchResults.java + if (rec != null) { + IArgBlock rarg = CMS.createArgBlock(); + + KeyRecordParser.fillRecordIntoArg(rec, rarg); + argSet.addRepeatRecord(rarg); + count++; + } + } + } + + header.addIntegerValue("maxSize", mMaxReturns); + header.addIntegerValue(OUT_TOTAL_COUNT, count); + ctx.addIntegerValue(OUT_MAXCOUNT, maxCount); + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java b/base/common/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java new file mode 100644 index 000000000..95c777701 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java @@ -0,0 +1,318 @@ +// --- 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.key; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X500Name; + +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.base.IArgBlock; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve archived keys matching given public key material + * + * + * @version $Revision$, $Date$ + */ +public class SrchKeyForRecovery extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 5426987963811540460L; + private final static String TPL_FILE = "srchKeyForRecovery.template"; + private final static String INFO = "srchKey"; + private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReturns"; + + // input parameters + private final static String IN_MAXCOUNT = "maxCount"; + private final static String IN_FILTER = "queryFilter"; + private final static String IN_SENTINEL = "querySentinel"; + + // output parameters + private final static String OUT_FILTER = IN_FILTER; + private final static String OUT_MAXCOUNT = IN_MAXCOUNT; + private final static String OUT_SENTINEL = IN_SENTINEL; + private final static String OUT_OP = "op"; + private final static String OUT_ERROR = "errorDetails"; + private final static String OUT_ARCHIVER = "archiverName"; + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_TOTAL_COUNT = "totalRecordCount"; + private final static String OUT_TEMPLATE = "templateName"; + + private IKeyRepository mKeyDB = null; + private X500Name mAuthName = null; + private String mFormPath = null; + private int mMaxReturns = 100; + private int mTimeLimits = 30; /* in seconds */ + + /** + * Constructs query key servlet. + */ + public SrchKeyForRecovery() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "srchKeyForRecovery.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); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + try { + String tmp = + sc.getInitParameter(PROP_MAX_SEARCH_RETURNS); + + if (tmp == null) + mMaxReturns = 100; + else + mMaxReturns = Integer.parseInt(tmp); + } catch (Exception e) { + // do nothing + } + + mKeyDB = ((IKeyRecoveryAuthority) mAuthority).getKeyRepository(); + mAuthName = ((IKeyRecoveryAuthority) mAuthority).getX500Name(); + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + /* Server-Side time limit */ + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + } + + /** + * Returns serlvet information. + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param maxCount maximum number of matches to show in result + * <li>http.param maxResults maximum number of matches to run in ldapsearch + * <li>http.param publicKeyData public key data to search on + * <li>http.param querySentinel ID of first request to show + * <li>http.param timeLimit number of seconds to limit ldap search to + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + + public void process(CMSRequest cmsReq) throws EBaseException { + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + // process query if authentication is successful + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + EBaseException error = null; + + int maxCount = -1; + int sentinel = 0; + int maxResults = -1; + int timeLimit = -1; + + try { + if (req.getParameter(IN_MAXCOUNT) != null) { + maxCount = Integer.parseInt( + req.getParameter(IN_MAXCOUNT)); + } + if (req.getParameter(IN_SENTINEL) != null) { + sentinel = Integer.parseInt( + req.getParameter(IN_SENTINEL)); + } + String maxResultsStr = req.getParameter("maxResults"); + + if (maxResultsStr != null && maxResultsStr.length() > 0) + maxResults = Integer.parseInt(maxResultsStr); + String timeLimitStr = req.getParameter("timeLimit"); + + if (timeLimitStr != null && timeLimitStr.length() > 0) + timeLimit = Integer.parseInt(timeLimitStr); + process(argSet, header, ctx, maxCount, maxResults, timeLimit, sentinel, + req.getParameter("publicKeyData"), req.getParameter(IN_FILTER), req, resp, locale[0]); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } + + /* + catch (Exception e) { + error = new EBaseException(BaseResources.INTERNAL_ERROR_1, e); + } + */ + + try { + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + ServletOutputStream out = resp.getOutputStream(); + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Process the key search. + */ + private void process(CMSTemplateParams argSet, + IArgBlock header, IArgBlock ctx, + int maxCount, int maxResults, int timeLimit, int sentinel, String publicKeyData, + String filter, + HttpServletRequest req, HttpServletResponse resp, Locale locale) + throws EBaseException { + + try { + // Fill header + header.addStringValue(OUT_OP, + req.getParameter(OUT_OP)); + header.addStringValue(OUT_ARCHIVER, + mAuthName.toString()); + // STRANGE: IE does not like the following: + // header.addStringValue(OUT_SERVICE_URL, + // req.getRequestURI()); + // XXX + header.addStringValue(OUT_SERVICE_URL, + "/kra?"); + header.addStringValue(OUT_TEMPLATE, + TPL_FILE); + header.addStringValue(OUT_FILTER, + filter); + if (publicKeyData != null) { + header.addStringValue("publicKeyData", + publicKeyData); + } + + if (timeLimit == -1 || timeLimit > mTimeLimits) { + CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits); + timeLimit = mTimeLimits; + } + CMS.debug("Start searching ... timelimit=" + timeLimit); + Enumeration<IKeyRecord> e = mKeyDB.searchKeys(filter, maxResults, timeLimit); + int count = 0; + + if (e == null) { + header.addStringValue(OUT_SENTINEL, + null); + } else { + while (e.hasMoreElements()) { + IKeyRecord rec = e.nextElement(); + // rec is null when we specify maxResults + // DS will return an err=4, which triggers + // a LDAPException.SIZE_LIMIT_ExCEEDED + // in DSSearchResults.java + if (rec != null) { + IArgBlock rarg = CMS.createArgBlock(); + + KeyRecordParser.fillRecordIntoArg(rec, rarg); + argSet.addRepeatRecord(rarg); + count++; + } + } + } + + header.addIntegerValue("maxSize", mMaxReturns); + header.addIntegerValue(OUT_TOTAL_COUNT, count); + ctx.addIntegerValue(OUT_MAXCOUNT, maxCount); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, "Error " + e); + throw e; + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java b/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java new file mode 100644 index 000000000..f479c6f0d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/model/KeyDAO.java @@ -0,0 +1,202 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.key.model; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.List; + +import javax.ws.rs.Path; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.keydb.IKeyRecord; +import com.netscape.certsrv.dbs.keydb.IKeyRepository; +import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.key.KeyResource; +import com.netscape.cms.servlet.request.model.RecoveryRequestData; + +/** + * @author alee + * + */ +public class KeyDAO { + + private IKeyRepository repo; + private IKeyRecoveryAuthority kra; + private IRequestQueue queue; + + public KeyDAO() { + kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" ); + repo = kra.getKeyRepository(); + queue = kra.getRequestQueue(); + } + /** + * Returns list of keys meeting specified search filter. + * Currently, vlv searches are not used for keys. + * + * @param filter + * @param maxResults + * @param maxTime + * @param uriInfo + * @return + * @throws EBaseException + */ + public KeyDataInfos listKeys(String filter, int maxResults, int maxTime, UriInfo uriInfo) + throws EBaseException { + List <KeyDataInfo> list = new ArrayList<KeyDataInfo>(); + Enumeration<IKeyRecord> e = null; + + e = repo.searchKeys(filter, maxResults, maxTime); + if (e == null) { + throw new EBaseException("search results are null"); + } + + while (e.hasMoreElements()) { + IKeyRecord rec = e.nextElement(); + if (rec != null) { + list.add(createKeyDataInfo(rec, uriInfo)); + } + } + + KeyDataInfos ret = new KeyDataInfos(); + ret.setKeyInfos(list); + + return ret; + } + + public KeyData getKey(KeyId keyId, RecoveryRequestData data) throws EBaseException { + KeyData keyData; + + RequestId rId = data.getRequestId(); + + String transWrappedSessionKey; + String sessionWrappedPassphrase; + + IRequest request = queue.findRequest(rId); + + if (request == null) { + return null; + } + + // get wrapped key + IKeyRecord rec = repo.readKeyRecord(keyId.toBigInteger()); + if (rec == null) { + return null; + } + + Hashtable<String, Object> requestParams = kra.getVolatileRequest( + request.getRequestId()); + + if(requestParams == null) { + throw new EBaseException("Can't obtain Volatile requestParams in KeyDAO.getKey!"); + } + + String sessWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_SESS_WRAPPED_DATA); + String passWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_PASS_WRAPPED_DATA); + String nonceData = (String) requestParams.get(IRequest.SECURITY_DATA_IV_STRING_OUT); + + if (sessWrappedKeyData != null || passWrappedKeyData != null) { + //The recovery process has already placed a valid recovery + //package, either session key wrapped or pass wrapped, into the request. + //Request already has been processed. + keyData = new KeyData(); + + } else { + // The request has not yet been processed, let's see if the RecoveryRequestData contains + // the info now needed to process the recovery request. + + transWrappedSessionKey = data.getTransWrappedSessionKey(); + sessionWrappedPassphrase = data.getSessionWrappedPassphrase(); + nonceData = data.getNonceData(); + + if (transWrappedSessionKey == null) { + //There must be at least a transWrappedSessionKey input provided. + //The command AND the request have provided insufficient data, end of the line. + throw new EBaseException("Can't retrieve key, insufficient input data!"); + } + + if (sessionWrappedPassphrase != null) { + requestParams.put(IRequest.SECURITY_DATA_SESS_PASS_PHRASE, sessionWrappedPassphrase); + } + + if (transWrappedSessionKey != null) { + requestParams.put(IRequest.SECURITY_DATA_TRANS_SESS_KEY, transWrappedSessionKey); + } + + if (nonceData != null) { + requestParams.put(IRequest.SECURITY_DATA_IV_STRING_IN, nonceData); + } + + try { + // Has to be in this state or it won't go anywhere. + request.setRequestStatus(RequestStatus.BEGIN); + queue.processRequest(request); + } catch (EBaseException e) { + kra.destroyVolatileRequest(request.getRequestId()); + throw new EBaseException(e.toString()); + } + + nonceData = null; + keyData = new KeyData(); + + sessWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_SESS_WRAPPED_DATA); + passWrappedKeyData = (String) requestParams.get(IRequest.SECURITY_DATA_PASS_WRAPPED_DATA); + nonceData = (String) requestParams.get(IRequest.SECURITY_DATA_IV_STRING_OUT); + + } + + if (sessWrappedKeyData != null) { + keyData.setWrappedPrivateData(sessWrappedKeyData); + } + if (passWrappedKeyData != null) { + keyData.setWrappedPrivateData(passWrappedKeyData); + } + if (nonceData != null) { + keyData.setNonceData(nonceData); + } + + kra.destroyVolatileRequest(request.getRequestId()); + + queue.markAsServiced(request); + + return keyData; + } + + public KeyDataInfo createKeyDataInfo(IKeyRecord rec, UriInfo uriInfo) throws EBaseException { + KeyDataInfo ret = new KeyDataInfo(); + + Path keyPath = KeyResource.class.getAnnotation(Path.class); + BigInteger serial = rec.getSerialNumber(); + + UriBuilder keyBuilder = uriInfo.getBaseUriBuilder(); + keyBuilder.path(keyPath.value() + "/" + serial); + ret.setKeyURL(keyBuilder.build().toString()); + + return ret; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java b/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java new file mode 100644 index 000000000..4f303e27d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/model/KeyData.java @@ -0,0 +1,76 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +/** + * + */ +package com.netscape.cms.servlet.key.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * @author alee + * + */ +@XmlRootElement(name="SecurityData") +@XmlAccessorType(XmlAccessType.FIELD) +public class KeyData { + @XmlElement + String wrappedPrivateData; + + @XmlElement + String nonceData; + + public KeyData() { + // required for JAXB (defaults) + } + + /** + * @return the wrappedPrivateData + */ + public String getWrappedPrivateData() { + return wrappedPrivateData; + } + + /** + * @param wrappedPrivateData the wrappedPrivateData to set + */ + public void setWrappedPrivateData(String wrappedPrivateData) { + this.wrappedPrivateData = wrappedPrivateData; + } + + /** + * @return the nonceData + */ + + public String getNonceData() { + return nonceData; + } + + /** + * @param nonceData the nonceData to set + */ + + public void setNonceData(String nonceData) { + this.nonceData = nonceData; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/key/model/KeyDataInfo.java b/base/common/src/com/netscape/cms/servlet/key/model/KeyDataInfo.java new file mode 100644 index 000000000..88b31b4d1 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/model/KeyDataInfo.java @@ -0,0 +1,85 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +/** + * + */ +package com.netscape.cms.servlet.key.model; + + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; + +import com.netscape.certsrv.dbs.keydb.KeyId; + +/** + * @author alee + * + */ +@XmlRootElement(name="SecurityDataInfo") +@XmlAccessorType(XmlAccessType.FIELD) +public class KeyDataInfo { + + @XmlElement + protected String keyURL; + + @XmlElement + protected String clientID; + + public KeyDataInfo() { + // required for JAXB (defaults) + } + + /** + * @return the keyURL + */ + public String getKeyURL() { + return keyURL; + } + + /** + * @param keyURL the keyURL to set + */ + public void setKeyURL(String keyURL) { + this.keyURL = keyURL; + } + + /** + * @return the key ID in the keyURL + */ + public KeyId getKeyId() { + String id = keyURL.substring(keyURL.lastIndexOf("/") + 1); + return new KeyId(id); + } + + /** + * @return the clientID + */ + public String getClientID() { + return clientID; + } + + /** + * @param clientID the clientID to set + */ + public void setClientID(String clientID) { + this.clientID = clientID; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/key/model/KeyDataInfos.java b/base/common/src/com/netscape/cms/servlet/key/model/KeyDataInfos.java new file mode 100644 index 000000000..b01184708 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/key/model/KeyDataInfos.java @@ -0,0 +1,87 @@ +// --- 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) 2012 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.key.model; + +import java.util.Collection; +import java.util.List; + +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.netscape.cms.servlet.base.model.Link; + +@XmlRootElement(name = "SecurityDataInfos") +public class KeyDataInfos { + + protected Collection<KeyDataInfo> keyInfos; + protected List<Link> links; + + /** + * @return the keyInfos + */ + @XmlElementRef + public Collection<KeyDataInfo> getKeyInfos() { + return keyInfos; + } + /** + * @param keyInfos the keyInfos to set + */ + public void setKeyInfos(Collection<KeyDataInfo> keyInfos) { + this.keyInfos = keyInfos; + } + /** + * @return the links + */ + @XmlElementRef + public List<Link> getLinks() { + return links; + } + /** + * @param links the links to set + */ + public void setLinks(List<Link> links) { + this.links = links; + } + + @XmlTransient + public String getNext() { + if (links == null) { + return null; + } + for (Link link : links) { + if ("next".equals(link.getRelationship())) { + return link.getHref(); + } + } + return null; + } + + @XmlTransient + public String getPrevious() { + if (links == null) { + return null; + } + for (Link link : links) { + if ("previous".equals(link.getRelationship())) { + return link.getHref(); + } + } + return null; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java new file mode 100644 index 000000000..1ef680853 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java @@ -0,0 +1,310 @@ +// --- 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.ocsp; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Cert; + +/** + * Configure the CA to respond to OCSP requests for a CA + * + * @version $Revision$ $Date$ + */ +public class AddCAServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1065151608542115340L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE-----"; + public static final String END_HEADER = + "-----END CERTIFICATE-----"; + + public static final BigInteger BIG_ZERO = new BigInteger("0"); + public static final Long MINUS_ONE = Long.valueOf(-1); + + private final static String TPL_FILE = "addCA.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + private final static String LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST = + "LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_3"; + private final static String LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED_3"; + + public AddCAServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "addCA.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); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param cert ca certificate. The format is base-64, DER encoded, wrapped with -----BEGIN CERTIFICATE-----, + * -----END CERTIFICATE----- strings + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST used when a CA is attempted to be added to the OCSP + * responder + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED used when an add CA request to the OCSP + * Responder is processed + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditCA = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String auditCASubjectDN = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + String uid = authToken.getInString(IAuthToken.USER_ID); + if (uid != null) { + CMS.debug("AddCAServlet: auditSubjectID set to " + uid); + auditSubjectID = uid; + } + } + String b64 = cmsReq.getHttpReq().getParameter("cert"); + + if (b64 == null) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST, + auditSubjectID, + ILogger.FAILURE, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CA_CERT")); + } + + auditCA = Cert.normalizeCertStr(Cert.stripCertBrackets(b64.trim())); + // record the fact that a request to add CA is made + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditCA); + + audit(auditMessage); + + if (b64.indexOf(BEGIN_HEADER) == -1) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_HEADER")); + } + if (b64.indexOf(END_HEADER) == -1) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_FOOTER")); + } + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + X509Certificate leafCert = null; + X509Certificate certs[] = null; + + try { + X509Certificate cert = Cert.mapCert(b64); + + if (cert == null) { + CMS.debug("AddCAServlet::process() - cert is null!"); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new EBaseException("cert is null"); + } else { + certs = new X509Certificate[1]; + } + + certs[0] = cert; + leafCert = cert; + auditCASubjectDN = leafCert.getSubjectDN().getName(); + } catch (Exception e) { + } + if (certs == null) { + try { + // this could be a chain + certs = Cert.mapCertFromPKCS7(b64); + if (certs[0].getSubjectDN().getName().equals(certs[0].getIssuerDN().getName())) { + leafCert = certs[certs.length - 1]; + } else { + leafCert = certs[0]; + } + auditCASubjectDN = leafCert.getSubjectDN().getName(); + } catch (Exception e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_CA_CHAIN_ERROR")); + } + } + if (certs != null && certs.length > 0) { + // (1) need to normalize (sort) the chain + + // (2) store certificate (and certificate chain) into + // database + ICRLIssuingPointRecord rec = defStore.createCRLIssuingPointRecord( + leafCert.getSubjectDN().getName(), + BIG_ZERO, + MINUS_ONE, null, null); + + try { + rec.set(ICRLIssuingPointRecord.ATTR_CA_CERT, leafCert.getEncoded()); + } catch (Exception e) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditCASubjectDN); + + audit(auditMessage); + + // error + } + defStore.addCRLIssuingPoint(leafCert.getSubjectDN().getName(), rec); + log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CA certificate " + leafCert.getSubjectDN().getName()); + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_ADD_CA_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditCASubjectDN); + + audit(auditMessage); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java new file mode 100644 index 000000000..2dec0e1f5 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java @@ -0,0 +1,591 @@ +// --- 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.ocsp; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRLException; +import java.security.cert.X509CRL; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CRLImpl; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509ExtensionException; + +import org.mozilla.jss.CryptoManager; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.dbs.repository.IRepositoryRecord; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Cert; + +/** + * Update the OCSP responder with a new CRL + * + * @version $Revision$ $Date$ + */ +public class AddCRLServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 1476080474638590902L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE REVOCATION LIST-----"; + public static final String END_HEADER = + "-----END CERTIFICATE REVOCATION LIST-----"; + + private final static String TPL_FILE = "addCRL.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + private final static String LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL = + "LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL_3"; + private final static String LOGGING_SIGNED_AUDIT_CRL_VALIDATION = + "LOGGING_SIGNED_AUDIT_CRL_VALIDATION_2"; + + public AddCRLServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "addCRL.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); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <P> + * + * <ul> + * <li>http.param crl certificate revocation list, base-64, DER encoded wrapped in -----BEGIN CERTIFICATE REVOCATION + * LIST-----, -----END CERTIFICATE REVOCATION LIST----- strings + * <li>http.param noui if true, use minimal hardcoded text response + * <li>signed.audit LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL used when CRLs are retrieved by the OCSP Responder ("agent" + * or "EE") + * <li>signed.audit LOGGING_SIGNED_AUDIT_CRL_VALIDATION used when CRL is retrieved and validation process occurs + * ("agent" or "EE") + * </ul> + * + * @param cmsReq the object holding the request and response information + * @exception EBaseException an error has occurred + */ + protected synchronized void process(CMSRequest cmsReq) + throws EBaseException { + boolean CRLFetched = false; + boolean CRLValidated = false; + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditCRLNum = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("add_crl", true /* main action */); + } + + try { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + return; + } + + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + if (authToken != null) { + String uid = authToken.getInString(IAuthToken.USER_ID); + if (uid != null) { + CMS.debug("AddCAServlet: auditSubjectID set to " + uid); + auditSubjectID = uid; + } + } + } + log(ILogger.LL_INFO, "AddCRLServlet"); + String b64 = cmsReq.getHttpReq().getParameter("crl"); + if (CMS.debugOn()) + CMS.debug("AddCRLServlet: b64=" + b64); + + if (b64 == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CRL")); + } + + String nouiParm = cmsReq.getHttpReq().getParameter("noui"); + boolean noUI = false; + + if (nouiParm != null && nouiParm.equals("true")) { + noUI = true; + CMS.debug("AddCRLServlet: noUI=true"); + } else { + CMS.debug("AddCRLServlet: noUI=false"); + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + if (!noUI) { + form = getTemplate(mFormPath, req, locale); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, + e.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + if (b64.indexOf(BEGIN_HEADER) == -1) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CRL_HEADER")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), + "CMS_GW_MISSING_CRL_HEADER")); + } + if (b64.indexOf(END_HEADER) == -1) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CRL_FOOTER")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), + "CMS_GW_MISSING_CRL_FOOTER")); + } + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + X509CRLImpl crl = null; + + try { + long startTime = CMS.getCurrentDate().getTime(); + CMS.debug("AddCRLServlet: mapCRL start startTime=" + startTime); + if (statsSub != null) { + statsSub.startTiming("decode_crl"); + } + crl = mapCRL1(b64); + if (statsSub != null) { + statsSub.endTiming("decode_crl"); + } + long endTime = CMS.getCurrentDate().getTime(); + CMS.debug("AddCRLServlet: mapCRL done endTime=" + endTime + + " diff=" + (endTime - startTime)); + + // Retrieve the actual CRL number + BigInteger crlNum = crl.getCRLNumber(); + if (crlNum != null) { + auditCRLNum = crlNum.toString(); + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.SUCCESS, + auditCRLNum); + + audit(auditMessage); + + // acknowledge that the CRL has been retrieved + CRLFetched = true; + } catch (Exception e) { + // error + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR")); + } + log(ILogger.LL_INFO, "AddCRLServlet: CRL Issuer DN " + + crl.getIssuerDN().getName()); + + ICRLIssuingPointRecord pt = null; + + try { + pt = defStore.readCRLIssuingPoint( + crl.getIssuerDN().getName()); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND", + crl.getIssuerDN().getName())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR")); + } + log(ILogger.LL_INFO, "AddCRLServlet: IssuingPoint " + + pt.getThisUpdate()); + + // verify CRL + byte caCertData[] = pt.getCACert(); + if (caCertData != null) { + try { + X509CertImpl caCert = new X509CertImpl(caCertData); + CMS.debug("AddCRLServlet: start verify"); + + CryptoManager cmanager = CryptoManager.getInstance(); + org.mozilla.jss.crypto.X509Certificate jssCert = null; + try { + jssCert = cmanager.importCACertPackage( + caCert.getEncoded()); + } catch (Exception e2) { + CMS.debug("AddCRLServlet: importCACertPackage " + + e2.toString()); + throw new EBaseException(e2.toString()); + } + + if (statsSub != null) { + statsSub.startTiming("verify_crl"); + } + crl.verify(jssCert.getPublicKey(), "Mozilla-JSS"); + if (statsSub != null) { + statsSub.endTiming("verify_crl"); + } + CMS.debug("AddCRLServlet: done verify"); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.SUCCESS); + + audit(auditMessage); + + // acknowledge that the CRL has been validated + CRLValidated = true; + } catch (Exception e) { + CMS.debug("AddCRLServlet: failed to verify CRL " + e.toString()); + CMS.debug(e); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_NO_CRL_ISSUING_POINT_FOUND", + crl.getIssuerDN().getName())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DECODING_CRL_ERROR")); + } + } + + if ((pt.getThisUpdate() != null) && + (pt.getThisUpdate().getTime() >= + crl.getThisUpdate().getTime())) { + // error, the uploaded CRL is older than the current + CMS.debug("AddCRLServlet: no update, CRL is older"); + log(ILogger.LL_INFO, + "AddCRLServlet: no update, received CRL is older " + + "than current CRL"); + if (noUI) { + try { + resp.setContentType("application/text"); + resp.getOutputStream().write("status=1\n".getBytes()); + resp.getOutputStream().write( + "error=Sent CRL is older than the current CRL\n".getBytes()); + resp.getOutputStream().flush(); + cmsReq.setStatus(CMSRequest.SUCCESS); + + // NOTE: The signed audit events + // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and + // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have + // already been logged at this point! + + return; + } catch (Exception e) { + } + } else { + CMS.debug("AddCRLServlet: CRL is older"); + + // NOTE: The signed audit events + // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and + // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have + // already been logged at this point! + + throw new ECMSGWException(CMS.getUserMessage( + "CMS_GW_OLD_CRL_ERROR")); + } + } + + if (crl.isDeltaCRL()) { + CMS.debug("AddCRLServlet: no update, Delta CRLs are not supported."); + log(ILogger.LL_INFO, "AddCRLServlet: no update, " + + CMS.getUserMessage("CMS_GW_DELTA_CRL_NOT_SUPPORTED")); + if (noUI) { + try { + resp.setContentType("application/text"); + resp.getOutputStream().write("status=1\n".getBytes()); + resp.getOutputStream().write( + "error=Delta CRLs are not supported.\n".getBytes()); + resp.getOutputStream().flush(); + cmsReq.setStatus(CMSRequest.SUCCESS); + + return; + } catch (Exception e) { + } + } else { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DELTA_CRL_NOT_SUPPORTED")); + } + } + + CMS.debug("AddCRLServlet: strt committing CRL"); + log(ILogger.LL_INFO, "AddCRLServlet: Start Committing CRL"); + + // ***************************************************** + // The commit transaction may take long time and + // there may have a system crash during the transaction + // ***************************************************** + + IRepositoryRecord repRec = defStore.createRepositoryRecord(); + + repRec.set(IRepositoryRecord.ATTR_SERIALNO, + new BigInteger(Long.toString(crl.getThisUpdate().getTime()))); + try { + defStore.addRepository( + crl.getIssuerDN().getName(), + Long.toString(crl.getThisUpdate().getTime()), + repRec); + log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CRL Updated " + + Long.toString(crl.getThisUpdate().getTime())); + } catch (Exception e) { + CMS.debug("AddCRLServlet: add repository e=" + e.toString()); + } + log(ILogger.LL_INFO, "AddCRLServlet: Created CRL Repository " + + Long.toString(crl.getThisUpdate().getTime())); + + if (defStore.waitOnCRLUpdate()) { + defStore.updateCRL(crl); + } else { + // when the CRL large, the thread is terminiated by the + // servlet framework before it can finish its work + UpdateCRLThread uct = new UpdateCRLThread(defStore, crl); + + uct.start(); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (noUI) { + CMS.debug("AddCRLServlet: return result noUI=true"); + resp.setContentType("application/text"); + resp.getOutputStream().write("status=0".getBytes()); + resp.getOutputStream().flush(); + cmsReq.setStatus(CMSRequest.SUCCESS); + } else { + CMS.debug("AddCRLServlet: return result noUI=false"); + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } + } catch (IOException e) { + CMS.debug("AddCRLServlet: return result error=" + e.toString()); + mOCSPAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", + e.toString())); + + // NOTE: The signed audit events + // LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL and + // LOGGING_SIGNED_AUDIT_CRL_VALIDATION have + // already been logged at this point! + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } catch (EBaseException eAudit1) { + if (!CRLFetched) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_RETRIEVAL, + auditSubjectID, + ILogger.FAILURE, + auditCRLNum); + + audit(auditMessage); + } else { + if (!CRLValidated) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CRL_VALIDATION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + } + } + throw eAudit1; + } + if (statsSub != null) { + statsSub.endTiming("add_crl"); + } + } + + public X509CRLImpl mapCRL1(String mime64) + throws IOException { + mime64 = Cert.stripCRLBrackets(mime64.trim()); + + byte rawPub[] = CMS.AtoB(mime64); + X509CRLImpl crl = null; + + try { + crl = new X509CRLImpl(rawPub, false); + } catch (Exception e) { + throw new IOException(e.toString()); + } + return crl; + } +} + +class UpdateCRLThread extends Thread { + private IDefStore mDefStore = null; + private X509CRL mCRL = null; + + public UpdateCRLThread( + IDefStore defStore, X509CRL crl) { + mDefStore = defStore; + mCRL = crl; + } + + public void run() { + try { + if (!((X509CRLImpl) mCRL).areEntriesIncluded()) + mCRL = new X509CRLImpl(((X509CRLImpl) mCRL).getEncoded()); + mDefStore.updateCRL(mCRL); + } catch (CRLException e) { + } catch (X509ExtensionException e) { + } catch (EBaseException e) { + // ignore + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java new file mode 100644 index 000000000..dfe796366 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java @@ -0,0 +1,216 @@ +// --- 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.ocsp; + +import java.io.IOException; +import java.security.cert.X509CRLEntry; +import java.security.cert.X509Certificate; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CRLImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cmsutil.util.Cert; + +/** + * Check the status of a specific certificate + * + * @version $Revision$ $Date$ + */ +public class CheckCertServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 7782198059640825050L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE-----"; + public static final String END_HEADER = + "-----END CERTIFICATE-----"; + + public static final String ATTR_STATUS = "status"; + public static final String ATTR_ISSUERDN = "issuerDN"; + public static final String ATTR_SUBJECTDN = "subjectDN"; + public static final String ATTR_SERIALNO = "serialno"; + + public static final String STATUS_GOOD = "good"; + public static final String STATUS_REVOKED = "revoked"; + public static final String STATUS_UNKNOWN = "unknown"; + + private final static String TPL_FILE = "checkCert.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + public CheckCertServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "checkCert.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); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param cert certificate to check. Base64, DER encoded, wrapped in -----BEGIN CERTIFICATE-----, -----END + * CERTIFICATE----- strings + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "validate"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + String b64 = cmsReq.getHttpReq().getParameter("cert"); + + if (b64.indexOf(BEGIN_HEADER) == -1) { + // error + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_HEADER")); + + } + if (b64.indexOf(END_HEADER) == -1) { + // error + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_FOOTER")); + } + + X509Certificate cert = null; + + try { + cert = Cert.mapCert(b64); + } catch (Exception e) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DECODING_CERT_ERROR")); + } + if (cert == null) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_DECODING_CERT_ERROR")); + } + + ICRLIssuingPointRecord pt = defStore.readCRLIssuingPoint( + cert.getIssuerDN().getName()); + + header.addStringValue(ATTR_ISSUERDN, cert.getIssuerDN().getName()); + header.addStringValue(ATTR_SUBJECTDN, cert.getSubjectDN().getName()); + header.addStringValue(ATTR_SERIALNO, "0x" + cert.getSerialNumber().toString(16)); + try { + X509CRLImpl crl = null; + + crl = new X509CRLImpl(pt.getCRL()); + X509CRLEntry crlentry = crl.getRevokedCertificate(cert.getSerialNumber()); + + if (crlentry == null) { + if (defStore.isNotFoundGood()) { + header.addStringValue(ATTR_STATUS, STATUS_GOOD); + } else { + header.addStringValue(ATTR_STATUS, STATUS_UNKNOWN); + } + } else { + header.addStringValue(ATTR_STATUS, STATUS_REVOKED); + } + } catch (Exception e) { + header.addStringValue(ATTR_STATUS, STATUS_UNKNOWN); + } + log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Checked Certificate Status " + + cert.getIssuerDN().getName() + " " + cert.getSerialNumber().toString()); + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java b/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java new file mode 100644 index 000000000..3dfc1d5f3 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java @@ -0,0 +1,164 @@ +// --- 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.ocsp; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IOCSPService; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Retrieve information about the number of OCSP requests the OCSP + * has serviced + * + * @version $Revision$, $Date$ + */ +public class GetOCSPInfo extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -3633557968127876119L; + private final static String TPL_FILE = "getOCSPInfo.template"; + private String mFormPath = null; + + public GetOCSPInfo() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template + * file "getOCSPInfo.template" to render the result page. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to display own output. + + // coming from agent + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + if (!(mAuthority instanceof IOCSPService)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_CA_FROM_RA_NOT_IMP")); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_NOT_YET_IMPLEMENTED"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, httpReq, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + return; + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IOCSPService ca = (IOCSPService) mAuthority; + + header.addLongValue("numReq", ca.getNumOCSPRequest()); + header.addLongValue("totalSec", ca.getOCSPRequestTotalTime()); + header.addLongValue("totalSignSec", ca.getOCSPTotalSignTime()); + header.addLongValue("totalLookupSec", ca.getOCSPTotalLookupTime()); + header.addLongValue("totalData", ca.getOCSPTotalData()); + long secs = 0; + if (ca.getOCSPRequestTotalTime() != 0) { + secs = (ca.getNumOCSPRequest() * 1000) / ca.getOCSPRequestTotalTime(); + } + header.addLongValue("ReqSec", secs); + try { + ServletOutputStream out = httpResp.getOutputStream(); + + httpResp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + cmsReq.setError(new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR"))); + cmsReq.setStatus(CMSRequest.ERROR); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java new file mode 100644 index 000000000..a93512ccd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java @@ -0,0 +1,198 @@ +// --- 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.ocsp; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.dbs.crldb.ICRLIssuingPointRecord; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Show the list of CA's that the OCSP responder can service + * + * @version $Revision$ $Date$ + */ +public class ListCAServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 3764395161795483452L; + public static final String BEGIN_HEADER = + "-----BEGIN CERTIFICATE-----"; + public static final String END_HEADER = + "-----END CERTIFICATE-----"; + + private final static String TPL_FILE = "listCAs.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + public ListCAServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "listCAs.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); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "list"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + Enumeration<ICRLIssuingPointRecord> recs = defStore.searchAllCRLIssuingPointRecord(100); + + // show the current CRL number if present + header.addStringValue("stateCount", + Integer.toString(defStore.getStateCount())); + + while (recs.hasMoreElements()) { + ICRLIssuingPointRecord rec = recs.nextElement(); + IArgBlock rarg = CMS.createArgBlock(); + String thisId = rec.getId(); + + rarg.addStringValue("Id", thisId); + Date thisUpdate = rec.getThisUpdate(); + + if (thisUpdate == null) { + rarg.addStringValue("ThisUpdate", "UNKNOWN"); + } else { + rarg.addStringValue("ThisUpdate", thisUpdate.toString()); + } + Date nextUpdate = rec.getNextUpdate(); + + if (nextUpdate == null) { + rarg.addStringValue("NextUpdate", "UNKNOWN"); + } else { + rarg.addStringValue("NextUpdate", nextUpdate.toString()); + } + Long rc = rec.getCRLSize(); + + if (rc == null) { + rarg.addLongValue("NumRevoked", 0); + } else { + if (rc.longValue() == -1) { + rarg.addStringValue("NumRevoked", "UNKNOWN"); + } else { + rarg.addLongValue("NumRevoked", rc.longValue()); + } + } + + BigInteger crlNumber = rec.getCRLNumber(); + if (crlNumber == null || crlNumber.equals(new BigInteger("-1"))) { + rarg.addStringValue("CRLNumber", "UNKNOWN"); + } else { + rarg.addStringValue("CRLNumber", crlNumber.toString()); + } + + rarg.addLongValue("ReqCount", defStore.getReqCount(thisId)); + argSet.addRepeatRecord(rarg); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java new file mode 100644 index 000000000..3ab20141c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java @@ -0,0 +1,276 @@ +// --- 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.ocsp; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mozilla.jss.asn1.ASN1Util; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.ocsp.IOCSPService; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.ocsp.BasicOCSPResponse; +import com.netscape.cmsutil.ocsp.OCSPRequest; +import com.netscape.cmsutil.ocsp.OCSPResponse; +import com.netscape.cmsutil.ocsp.ResponseBytes; +import com.netscape.cmsutil.ocsp.ResponseData; +import com.netscape.cmsutil.ocsp.SingleResponse; +import com.netscape.cmsutil.ocsp.TBSRequest; +import com.netscape.cmsutil.util.Utils; + +/** + * Process OCSP messages, According to RFC 2560 + * See http://www.ietf.org/rfc/rfc2560.txt + * + * @version $Revision$ $Date$ + */ +public class OCSPServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 120903601883352030L; + public final static String PROP_AUTHORITY = "authority"; + public final static String PROP_CLIENTAUTH = "GetClientCert"; + public final static String PROP_MAX_REQUEST_SIZE = "MaxRequestSize"; + public final static String PROP_ID = "ID"; + + private int m_maxRequestSize = 5000; + + public OCSPServlet() { + 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); + String s = sc.getInitParameter(PROP_MAX_REQUEST_SIZE); + if (s != null) { + try { + m_maxRequestSize = Integer.parseInt(s); + } catch (Exception e) { + } + } + + } + + /** + * Process the HTTP request. + * This method is invoked when the OCSP service receives a OCSP + * request. Based on RFC 2560, the request should have the OCSP + * request in the HTTP body as binary blob. + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IStatsSubsystem statsSub = (IStatsSubsystem) CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("ocsp", true /* main action */); + } + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "submit"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMS.debug("Servlet Path=" + httpReq.getServletPath()); + CMS.debug("RequestURI=" + httpReq.getRequestURI()); + String pathInfo = httpReq.getPathInfo(); + if (pathInfo != null && pathInfo.indexOf('%') != -1) { + try { + pathInfo = URLDecoder.decode(pathInfo, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + throw new EBaseException("OCSPServlet: Unsupported encoding" + e); + } + } + CMS.debug("PathInfo=" + pathInfo); + + OCSPRequest ocspReq = null; + + try { + InputStream is = httpReq.getInputStream(); + byte reqbuf[] = null; + String method = httpReq.getMethod(); + CMS.debug("Method=" + method); + if (method != null && method.equals("POST")) { + int reqlen = httpReq.getContentLength(); + + if (reqlen == -1) { + throw new Exception("OCSPServlet: Content-Length not supplied"); + } + if (reqlen == 0) { + throw new Exception("OCSPServlet: Invalid Content-Length"); + } + if (reqlen > m_maxRequestSize) { + throw new Exception("OCSPServlet: Client sending too much OCSP request data (" + reqlen + ")"); + } + + // for debugging + reqbuf = new byte[reqlen]; + int bytesread = 0; + boolean partial = false; + + while (bytesread < reqlen) { + int r = is.read(reqbuf, bytesread, reqlen - bytesread); + if (r == -1) { + throw new Exception("OCSPServlet: Client did not supply enough OCSP data"); + } + bytesread += r; + if (partial == false) { + if (bytesread < reqlen) { + partial = true; + } + } + } + is = new ByteArrayInputStream(reqbuf); + } else { + // GET method + if ((pathInfo == null) || + (pathInfo.equals("")) || + (pathInfo.substring(1) == null) || + (pathInfo.substring(1).equals(""))) { + throw new Exception("OCSPServlet: OCSP request not provided in GET method"); + } + is = new ByteArrayInputStream( + Utils.base64decode(pathInfo.substring(1))); + } + + // (1) retrieve OCSP request + // (2) decode request + OCSPResponse response = null; + + try { + OCSPRequest.Template reqTemplate = + new OCSPRequest.Template(); + + if ((is == null) || + (is.toString().equals(""))) { + throw new Exception("OCSPServlet: OCSP request is " + + "empty or malformed"); + } + ocspReq = (OCSPRequest) reqTemplate.decode(is); + if ((ocspReq == null) || + (ocspReq.toString().equals(""))) { + throw new Exception("OCSPServlet: Decoded OCSP request " + + "is empty or malformed"); + } + response = ((IOCSPService) mAuthority).validate(ocspReq); + } catch (Exception e) { + ; + CMS.debug("OCSPServlet: " + e.toString()); + } + + if (response != null) { + ByteArrayOutputStream fos1 = new ByteArrayOutputStream(); + + response.encode(fos1); + fos1.close(); + + byte[] respbytes; + + respbytes = fos1.toByteArray(); + + // print out OCSP response in debug mode so that + // we can validate the response + if (CMS.debugOn()) { + CMS.debug("OCSPServlet: OCSP Request:"); + CMS.debug("OCSPServlet: " + CMS.BtoA(ASN1Util.encode(ocspReq))); + TBSRequest tbsReq = ocspReq.getTBSRequest(); + for (int i = 0; i < tbsReq.getRequestCount(); i++) { + com.netscape.cmsutil.ocsp.Request req = tbsReq.getRequestAt(i); + CMS.debug("Serial Number: " + req.getCertID().getSerialNumber()); + } + CMS.debug("OCSPServlet: OCSP Response Size:"); + CMS.debug("OCSPServlet: " + Integer.toString(respbytes.length)); + CMS.debug("OCSPServlet: OCSP Response Data:"); + CMS.debug("OCSPServlet: " + CMS.BtoA(respbytes)); + ResponseBytes rbytes = response.getResponseBytes(); + if (rbytes == null) { + CMS.debug("Response bytes is null"); + } else if (rbytes.getObjectIdentifier().equals( + ResponseBytes.OCSP_BASIC)) { + BasicOCSPResponse basicRes = (BasicOCSPResponse) + BasicOCSPResponse.getTemplate().decode( + new ByteArrayInputStream(rbytes.getResponse().toByteArray())); + if (basicRes == null) { + CMS.debug("Basic Res is null"); + } else { + ResponseData data = basicRes.getResponseData(); + for (int i = 0; i < data.getResponseCount(); i++) { + SingleResponse res = data.getResponseAt(i); + CMS.debug("Serial Number: " + + res.getCertID().getSerialNumber() + + " Status: " + + res.getCertStatus().getClass().getName()); + } + } + } + } + + httpResp.setContentType("application/ocsp-response"); + + httpResp.setContentLength(respbytes.length); + OutputStream ooss = httpResp.getOutputStream(); + + ooss.write(respbytes); + ooss.flush(); + if (statsSub != null) { + statsSub.endTiming("ocsp"); + } + + mRenderResult = false; + } + } catch (Exception e) { + CMS.debug("OCSPServlet: " + e.toString()); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java b/base/common/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java new file mode 100644 index 000000000..4262940d0 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/ocsp/RemoveCAServlet.java @@ -0,0 +1,214 @@ +// --- 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.ocsp; + +import java.io.IOException; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ocsp.IDefStore; +import com.netscape.certsrv.ocsp.IOCSPAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Configure the CA to no longer respond to OCSP requests for a CA + * + * @version $Revision: 1274 $ $Date: 2010-09-07 22:14:41 -0700 (Tue, 07 Sep 2010) $ + */ +public class RemoveCAServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -4519898238552366358L; + private final static String TPL_FILE = "removeCA.template"; + private String mFormPath = null; + private IOCSPAuthority mOCSPAuthority = null; + + private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST = + "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_3"; + private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS_3"; + + private final static String LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE_3"; + + public RemoveCAServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "addCA.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); + // override success to display own output. + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + mTemplates.remove(CMSRequest.SUCCESS); + mOCSPAuthority = (IOCSPAuthority) mAuthority; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param ca id. The format is string. + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST used when a CA is attempted to be removed from the + * OCSP responder + * <li>signed.audit LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS and + * LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE are used when a remove CA request to the OCSP + * Responder is processed successfully or not. + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + protected void process(CMSRequest cmsReq) + throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + if (auditSubjectID.equals(ILogger.NONROLEUSER) || + auditSubjectID.equals(ILogger.UNIDENTIFIED)) { + String uid = authToken.getInString(IAuthToken.USER_ID); + if (uid != null) { + CMS.debug("RemoveCAServlet: auditSubjectID set to " + uid); + auditSubjectID = uid; + } + } + + String caID = cmsReq.getHttpReq().getParameter("caID"); + + if (caID == null) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE, + auditSubjectID, + ILogger.FAILURE, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CA_ID")); + } + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + caID); + + audit(auditMessage); + + IDefStore defStore = mOCSPAuthority.getDefaultStore(); + + try { + defStore.deleteCRLIssuingPointRecord(caID); + + } catch (EBaseException e) { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_FAILURE, + auditSubjectID, + ILogger.FAILURE, + caID); + audit(auditMessage); + + CMS.debug("RemoveCAServlet::process: Error deleting CRL IssuingPoint: " + caID); + throw new EBaseException(e.toString()); + } + + CMS.debug("RemoveCAServlet::process: CRL IssuingPoint for CA successfully removed: " + caID); + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_OCSP_REMOVE_CA_REQUEST_PROCESSED_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + caID); + audit(auditMessage); + + try { + ServletOutputStream out = resp.getOutputStream(); + + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/processors/CMCProcessor.java b/base/common/src/com/netscape/cms/servlet/processors/CMCProcessor.java new file mode 100644 index 000000000..53c13510d --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/processors/CMCProcessor.java @@ -0,0 +1,433 @@ +// --- 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.processors; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.security.PublicKey; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Hashtable; + +import netscape.security.pkcs.PKCS10; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.pkcs10.CertificationRequest; +import org.mozilla.jss.pkcs11.PK11PubKey; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cert.CertificateInfo; +import org.mozilla.jss.pkix.cmc.PKIData; +import org.mozilla.jss.pkix.cmc.TaggedAttribute; +import org.mozilla.jss.pkix.cmc.TaggedCertificationRequest; +import org.mozilla.jss.pkix.cmc.TaggedRequest; +import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo; +import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber; +import org.mozilla.jss.pkix.cms.SignedData; +import org.mozilla.jss.pkix.cms.SignerIdentifier; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.Name; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Process CMC messages according to RFC 2797 + * See http://www.ietf.org/rfc/rfc2797.txt + * + * @version $Revision$, $Date$ + */ +public class CMCProcessor extends PKIProcessor { + + private boolean enforcePop = false; + + public CMCProcessor() { + super(); + } + + public CMCProcessor(CMSRequest cmsReq, CMSServlet servlet, boolean doEnforcePop) { + + super(cmsReq, servlet); + enforcePop = doEnforcePop; + + } + + public void process(CMSRequest cmsReq) + throws EBaseException { + } + + public void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + } + + public X509CertInfo[] fillCertInfoArray( + String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req) + throws EBaseException { + + CMS.debug("CMCProcessor: In CMCProcessor.fillCertInfoArray!"); + String cmc = protocolString; + + try { + byte[] cmcBlob = CMS.AtoB(cmc); + ByteArrayInputStream cmcBlobIn = + new ByteArrayInputStream(cmcBlob); + + org.mozilla.jss.pkix.cms.ContentInfo cmcReq = (org.mozilla.jss.pkix.cms.ContentInfo) + org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn); + + if (!cmcReq.getContentType().equals(org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA) + || !cmcReq.hasContent()) + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_CMC_CONTENT")); + + SignedData cmcFullReq = (SignedData) + cmcReq.getInterpretedContent(); + + EncapsulatedContentInfo ci = cmcFullReq.getContentInfo(); + + OBJECT_IDENTIFIER id = ci.getContentType(); + + if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) || !ci.hasContent()) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_NO_PKIDATA")); + } + OCTET_STRING content = ci.getContent(); + + ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray()); + PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s); + + SEQUENCE reqSequence = pkiData.getReqSequence(); + + int numReqs = reqSequence.size(); + X509CertInfo[] certInfoArray = new X509CertInfo[numReqs]; + String[] reqIdArray = new String[numReqs]; + + for (int i = 0; i < numReqs; i++) { + // decode message. + TaggedRequest taggedRequest = (TaggedRequest) reqSequence.elementAt(i); + + TaggedRequest.Type type = taggedRequest.getType(); + + if (type.equals(TaggedRequest.PKCS10)) { + TaggedCertificationRequest tcr = taggedRequest.getTcr(); + int p10Id = tcr.getBodyPartID().intValue(); + + reqIdArray[i] = String.valueOf(p10Id); + + CertificationRequest p10 = + tcr.getCertificationRequest(); + + // transfer to sun class + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + p10.encode(ostream); + + PKCS10Processor pkcs10Processor = new PKCS10Processor(mRequest, mServlet); + + try { + PKCS10 pkcs10 = new PKCS10(ostream.toByteArray()); + //xxx do we need to do anything else? + X509CertInfo certInfo = CMS.getDefaultX509CertInfo(); + + pkcs10Processor.fillCertInfo(pkcs10, certInfo, authToken, httpParams); + + /* fillPKCS10(pkcs10,certInfo, + authToken, httpParams); + */ + + certInfoArray[i] = certInfo; + } catch (Exception e) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_PKCS10_ERROR", e.toString())); + } + } else if (type.equals(TaggedRequest.CRMF)) { + + CRMFProcessor crmfProc = new CRMFProcessor(mRequest, mServlet, enforcePop); + + CertReqMsg crm = taggedRequest.getCrm(); + CertRequest certReq = crm.getCertReq(); + + INTEGER certReqId = certReq.getCertReqId(); + int srcId = certReqId.intValue(); + + reqIdArray[i] = String.valueOf(srcId); + + certInfoArray[i] = crmfProc.processIndividualRequest(crm, authToken, httpParams); + + } else { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_CMC_CONTENT")); + } + } + + // verify the signerInfo + SET dais = cmcFullReq.getDigestAlgorithmIdentifiers(); + int numDig = dais.size(); + Hashtable<String, byte[]> digs = new Hashtable<String, byte[]>(); + + for (int i = 0; i < numDig; i++) { + AlgorithmIdentifier dai = + (AlgorithmIdentifier) dais.elementAt(i); + String name = + DigestAlgorithm.fromOID(dai.getOID()).toString(); + + MessageDigest md = + MessageDigest.getInstance(name); + + byte[] digest = md.digest(content.toByteArray()); + + digs.put(name, digest); + } + + SET sis = cmcFullReq.getSignerInfos(); + int numSis = sis.size(); + + for (int i = 0; i < numSis; i++) { + org.mozilla.jss.pkix.cms.SignerInfo si = + (org.mozilla.jss.pkix.cms.SignerInfo) + sis.elementAt(i); + + String name = si.getDigestAlgorithm().toString(); + byte[] digest = (byte[]) digs.get(name); + + if (digest == null) { + MessageDigest md = MessageDigest.getInstance(name); + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + pkiData.encode((OutputStream) ostream); + digest = md.digest(ostream.toByteArray()); + + } + + SignerIdentifier sid = si.getSignerIdentifier(); + + if (sid.getType().equals(SignerIdentifier.ISSUER_AND_SERIALNUMBER)) { + IssuerAndSerialNumber issuerAndSerialNumber = sid.getIssuerAndSerialNumber(); + // find from the certs in the signedData + X509Certificate cert = null; + + if (cmcFullReq.hasCertificates()) { + SET certs = cmcFullReq.getCertificates(); + int numCerts = certs.size(); + + for (int j = 0; j < numCerts; j++) { + Certificate certJss = + (Certificate) certs.elementAt(j); + CertificateInfo certI = + certJss.getInfo(); + Name issuer = certI.getIssuer(); + byte[] issuerB = ASN1Util.encode(issuer); + + INTEGER sn = certI.getSerialNumber(); + + if (new String(issuerB).equals(new + String(ASN1Util.encode(issuerAndSerialNumber.getIssuer()))) + && sn.toString().equals(issuerAndSerialNumber.getSerialNumber().toString())) { + ByteArrayOutputStream os = new + ByteArrayOutputStream(); + + certJss.encode(os); + cert = new X509CertImpl(os.toByteArray()); + // xxx validate the cert length + + } + } + + } + // find from internaldb if it's ca. (ra does not have that.) + // find from internaldb usrgrp info + + if (cert == null) { + // find from certDB + si.verify(digest, id); + } else { + PublicKey signKey = cert.getPublicKey(); + PrivateKey.Type keyType = null; + String alg = signKey.getAlgorithm(); + + if (alg.equals("RSA")) { + keyType = PrivateKey.RSA; + } else if (alg.equals("DSA")) { + keyType = PrivateKey.DSA; + } else { + } + PK11PubKey pubK = + PK11PubKey.fromRaw(keyType, + ((X509Key) signKey).getKey()); + + si.verify(digest, id, pubK); + } + + } else { + OCTET_STRING ski = sid.getSubjectKeyIdentifier(); + // find the publicKey using ski + int j = 0; + PublicKey signKey = null; + + while (signKey == null && j < numReqs) { + X509Key subjectKeyInfo = + (X509Key) ((CertificateX509Key) certInfoArray[j].get(X509CertInfo.KEY)) + .get(CertificateX509Key.KEY); + MessageDigest md = MessageDigest.getInstance("SHA-1"); + + md.update(subjectKeyInfo.getEncoded()); + byte[] skib = md.digest(); + + if (new String(skib).equals(new String(ski.toByteArray()))) { + signKey = subjectKeyInfo; + } + j++; + } + if (signKey == null) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CMC_ERROR", + "SubjectKeyIdentifier in SignerInfo does not match any publicKey in the request.")); + } else { + PrivateKey.Type keyType = null; + String alg = signKey.getAlgorithm(); + + if (alg.equals("RSA")) { + keyType = PrivateKey.RSA; + } else if (alg.equals("DSA")) { + keyType = PrivateKey.DSA; + } else { + } + PK11PubKey pubK = PK11PubKey.fromRaw( + keyType, + ((X509Key) signKey).getKey()); + + si.verify(digest, id, pubK); + } + } + } + // end verify signerInfo + + // Get control sequence + // verisign has transactionId, senderNonce, regInfo + // identification, identityproof + SEQUENCE controls = pkiData.getControlSequence(); + int numControls = controls.size(); + + for (int i = 0; i < numControls; i++) { + TaggedAttribute control = + (TaggedAttribute) controls.elementAt(i); + OBJECT_IDENTIFIER type = control.getType(); + SET values = control.getValues(); + int numVals = values.size(); + + if (type.equals(OBJECT_IDENTIFIER.id_cmc_transactionId)) { + String[] vals = null; + + if (numVals > 0) + vals = new String[numVals]; + for (int j = 0; j < numVals; j++) { + ANY val = (ANY) + values.elementAt(j); + INTEGER transId = (INTEGER) ((ANY) val).decodeWith( + INTEGER.getTemplate()); + + if (transId != null) { + vals[j] = transId.toString(); + } + } + if (vals != null) + req.setExtData(IRequest.CMC_TRANSID, vals); + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_senderNonce)) { + String[] vals = null; + + if (numVals > 0) + vals = new String[numVals]; + for (int j = 0; j < numVals; j++) { + ANY val = (ANY) + values.elementAt(j); + OCTET_STRING nonce = (OCTET_STRING) + ((ANY) val).decodeWith(OCTET_STRING.getTemplate()); + + if (nonce != null) { + vals[j] = new String(nonce.toByteArray()); + } + } + if (vals != null) + req.setExtData(IRequest.CMC_SENDERNONCE, vals); + + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_regInfo)) { + // what can we do here + // for verisign, we just debug.print() + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_identification)) { + // what can we do here + // for verisign, we just debug.print() + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_identityProof)) { + // what can we do here + // for verisign, we just debug.print() + } + } + + req.setExtData(IRequest.CMC_REQIDS, reqIdArray); + return certInfoArray; + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (InvalidBERException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (InvalidKeyException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CMC_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_TO_CERTINFO_ERROR")); + } catch (Exception e) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CMC_ERROR", e.toString())); + } + + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/processors/CRMFProcessor.java b/base/common/src/com/netscape/cms/servlet/processors/CRMFProcessor.java new file mode 100644 index 000000000..2d2f1430e --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/processors/CRMFProcessor.java @@ -0,0 +1,372 @@ +// --- 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.processors; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; + +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.ProofOfPossession; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Process CRMF requests, according to RFC 2511 + * See http://www.ietf.org/rfc/rfc2511.txt + * + * @version $Revision$, $Date$ + */ +public class CRMFProcessor extends PKIProcessor { + + private CMSRequest mRequest; + + private boolean enforcePop = false; + + private final static String LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION = + "LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION_2"; + + public CRMFProcessor() { + super(); + } + + public CRMFProcessor(CMSRequest cmsReq, CMSServlet servlet, boolean doEnforcePop) { + super(cmsReq, servlet); + + enforcePop = doEnforcePop; + mRequest = cmsReq; + } + + public void process(CMSRequest cmsReq) + throws EBaseException { + } + + /** + * Verify Proof of Possession (POP) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION used when proof of possession is checked during + * certificate enrollment + * </ul> + * + * @param certReqMsg the certificate request message + * @exception EBaseException an error has occurred + */ + private void verifyPOP(CertReqMsg certReqMsg) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + + try { + CMS.debug("CRMFProcessor: verifyPOP"); + + if (certReqMsg.hasPop()) { + ProofOfPossession pop = certReqMsg.getPop(); + + ProofOfPossession.Type popType = pop.getType(); + + if (popType == ProofOfPossession.SIGNATURE) { + CMS.debug("CRMFProcessor: Request has pop."); + try { + certReqMsg.verify(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.SUCCESS); + + audit(auditMessage); + } catch (Exception e) { + CMS.debug("CRMFProcessor: Failed POP verify!"); + + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_POP_VERIFY")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_POP_VERIFY")); + } + } + } else { + if (enforcePop == true) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_NO_POP")); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + + throw new ECMSGWException( + CMS.getLogMessage("CMSGW_ERROR_NO_POP")); + } + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROOF_OF_POSSESSION, + auditSubjectID, + ILogger.FAILURE); + + audit(auditMessage); + } + } + + public X509CertInfo processIndividualRequest(CertReqMsg certReqMsg, IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + CMS.debug("CRMFProcessor::processIndividualRequest!"); + + try { + + verifyPOP(certReqMsg); + + CertRequest certReq = certReqMsg.getCertReq(); + + CertTemplate certTemplate = certReq.getCertTemplate(); + X509CertInfo certInfo = CMS.getDefaultX509CertInfo(); + + // get key + SubjectPublicKeyInfo spki = certTemplate.getPublicKey(); + ByteArrayOutputStream keyout = new ByteArrayOutputStream(); + + spki.encode(keyout); + byte[] keybytes = keyout.toByteArray(); + X509Key key = new X509Key(); + + key.decode(keybytes); + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + + // field suggested notBefore and notAfter in CRMF + // Tech Support #383184 + if (certTemplate.getNotBefore() != null || certTemplate.getNotAfter() != null) { + CertificateValidity certValidity = + new CertificateValidity(certTemplate.getNotBefore(), certTemplate.getNotAfter()); + + certInfo.set(X509CertInfo.VALIDITY, certValidity); + } + + if (certTemplate.hasSubject()) { + Name subjectdn = certTemplate.getSubject(); + ByteArrayOutputStream subjectEncStream = + new ByteArrayOutputStream(); + + subjectdn.encode(subjectEncStream); + byte[] subjectEnc = subjectEncStream.toByteArray(); + X500Name subject = new X500Name(subjectEnc); + + certInfo.set(X509CertInfo.SUBJECT, + new CertificateSubjectName(subject)); + } else if (authToken == null || + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) { + // No subject name - error! + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + } + + // get extensions + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) + certInfo.get(X509CertInfo.EXTENSIONS); + } catch (CertificateException e) { + extensions = null; + } catch (IOException e) { + extensions = null; + } + if (certTemplate.hasExtensions()) { + // put each extension from CRMF into CertInfo. + // index by extension name, consistent with + // CertificateExtensions.parseExtension() method. + if (extensions == null) + extensions = new CertificateExtensions(); + int numexts = certTemplate.numExtensions(); + + for (int j = 0; j < numexts; j++) { + org.mozilla.jss.pkix.cert.Extension jssext = + certTemplate.extensionAt(j); + boolean isCritical = jssext.getCritical(); + org.mozilla.jss.asn1.OBJECT_IDENTIFIER jssoid = + jssext.getExtnId(); + long[] numbers = jssoid.getNumbers(); + int[] oidNumbers = new int[numbers.length]; + + for (int k = numbers.length - 1; k >= 0; k--) { + oidNumbers[k] = (int) numbers[k]; + } + ObjectIdentifier oid = + new ObjectIdentifier(oidNumbers); + org.mozilla.jss.asn1.OCTET_STRING jssvalue = + jssext.getExtnValue(); + ByteArrayOutputStream jssvalueout = + new ByteArrayOutputStream(); + + jssvalue.encode(jssvalueout); + byte[] extValue = jssvalueout.toByteArray(); + + Extension ext = + new Extension(oid, isCritical, extValue); + + extensions.parseExtension(ext); + } + + certInfo.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + certInfo.set(X509CertInfo.EXTENSIONS, extensions); + + } + + // Added a new configuration parameter + // eeGateway.Enrollment.authTokenOverride=[true|false] + // By default, it is set to true. In most + // of the case, administrator would want + // to have the control of the subject name + // formulation. + // -- CRMFfillCert + if (authToken != null && + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null) { + // if authenticated override subect name, validity and + // extensions if any from authtoken. + fillCertInfoFromAuthToken(certInfo, authToken); + } + + // SPECIAL CASE: + // if it is adminEnroll servlet, get the validity + // from the http parameters. + if (mServletId.equals(PKIProcessor.ADMIN_ENROLL_SERVLET_ID)) { + fillValidityFromForm(certInfo, httpParams); + } + + return certInfo; + + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } /* catch (InvalidBERException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1",e.toString())); + throw new ECMSGWException( + CMSGWResources.ERROR_CRMF_TO_CERTINFO); + } */catch (InvalidKeyException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } + + } + + public X509CertInfo[] fillCertInfoArray( + String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req) + throws EBaseException { + + CMS.debug("CRMFProcessor.fillCertInfoArray!"); + + String crmf = protocolString; + + try { + byte[] crmfBlob = CMS.AtoB(crmf); + ByteArrayInputStream crmfBlobIn = + new ByteArrayInputStream(crmfBlob); + + SEQUENCE crmfMsgs = (SEQUENCE) + new SEQUENCE.OF_Template(new CertReqMsg.Template()).decode(crmfBlobIn); + + int nummsgs = crmfMsgs.size(); + X509CertInfo[] certInfoArray = new X509CertInfo[nummsgs]; + + for (int i = 0; i < nummsgs; i++) { + // decode message. + CertReqMsg certReqMsg = (CertReqMsg) crmfMsgs.elementAt(i); + + CertRequest certReq = certReqMsg.getCertReq(); + INTEGER certReqId = certReq.getCertReqId(); + int srcId = certReqId.intValue(); + + req.setExtData(IRequest.CRMF_REQID, String.valueOf(srcId)); + + certInfoArray[i] = processIndividualRequest(certReqMsg, authToken, httpParams); + + } + + //do_testbed_hack(nummsgs, certInfoArray, httpParams); + + return certInfoArray; + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } catch (InvalidBERException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_CRMF_TO_CERTINFO_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CRMF_TO_CERTINFO_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/processors/IPKIProcessor.java b/base/common/src/com/netscape/cms/servlet/processors/IPKIProcessor.java new file mode 100644 index 000000000..9139f888c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/processors/IPKIProcessor.java @@ -0,0 +1,33 @@ +// --- 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.processors; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.cms.servlet.common.CMSRequest; + +/** + * This represents the request parser. + * + * @version $Revision$, $Date$ + */ +public interface IPKIProcessor { + + public void process(CMSRequest cmsReq) + throws EBaseException; + +} diff --git a/base/common/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java b/base/common/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java new file mode 100644 index 000000000..cfe9754a8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java @@ -0,0 +1,120 @@ +// --- 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.processors; + +import java.io.IOException; +import java.security.cert.CertificateException; + +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.KeyGenInfo; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * KeyGenProcess parses Certificate request matching the + * KEYGEN tag format used by Netscape Communicator 4.x + * + * @version $Revision$, $Date$ + */ +public class KeyGenProcessor extends PKIProcessor { + + public KeyGenProcessor() { + super(); + } + + public KeyGenProcessor(CMSRequest cmsReq, CMSServlet servlet) { + super(cmsReq, servlet); + + } + + public void process(CMSRequest cmsReq) + throws EBaseException { + } + + public void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + + CMS.debug("KeyGenProcessor: fillCertInfo"); + + if (mServlet == null) { + return; + } + + KeyGenInfo keyGenInfo = httpParams.getValueAsKeyGenInfo( + PKIProcessor.SUBJECT_KEYGEN_INFO, null); + + // fill key + X509Key key = null; + + key = keyGenInfo.getSPKI(); + if (key == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_KEY_IN_KEYGENINFO")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_KEY_IN_KEYGENINFO")); + } + try { + certInfo.set(X509CertInfo.KEY, new CertificateX509Key(key)); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + "Could not set key into certInfo from keygen. Error " + e); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_KEYGEN_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_KEY_FROM_KEYGEN_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_KEYGEN_FAILED", e.toString())); + } + + String authMgr = mServlet.getAuthMgr(); + + // if not authenticated, fill subject name, validity & extensions + // from authtoken. + if (authToken == null) { + fillCertInfoFromForm(certInfo, httpParams); + } else { + if (authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) { + // allow special case for agent gateway in admin enroll + // and bulk issuance. + if (!authMgr.equals(IAuthSubsystem.CERTUSERDB_AUTHMGR_ID) && + !authMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID)) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_NAME_FROM_AUTHTOKEN")); + } + fillCertInfoFromForm(certInfo, httpParams); + } else { + fillCertInfoFromAuthToken(certInfo, authToken); + } + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/processors/PKCS10Processor.java b/base/common/src/com/netscape/cms/servlet/processors/PKCS10Processor.java new file mode 100644 index 000000000..dad4b64ab --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/processors/PKCS10Processor.java @@ -0,0 +1,287 @@ +// --- 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.processors; + +import java.io.IOException; +import java.security.cert.CertificateException; + +import netscape.security.pkcs.PKCS10; +import netscape.security.pkcs.PKCS10Attribute; +import netscape.security.pkcs.PKCS10Attributes; +import netscape.security.pkcs.PKCS9Attribute; +import netscape.security.util.DerInputStream; +import netscape.security.util.DerOutputStream; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extensions; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthSubsystem; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * PKCS10Processor process Certificate Requests in + * PKCS10 format, as defined here: + * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-10/index.html + * + * @version $Revision$, $Date$ + */ +public class PKCS10Processor extends PKIProcessor { + + private PKCS10 mPkcs10 = null; + + private final String USE_INTERNAL_PKCS10 = "internal"; + + public PKCS10Processor() { + + super(); + } + + public PKCS10Processor(CMSRequest cmsReq, CMSServlet servlet) { + super(cmsReq, servlet); + + } + + public void process(CMSRequest cmsReq) + throws EBaseException { + } + + public void fillCertInfo( + PKCS10 pkcs10, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + + mPkcs10 = pkcs10; + + fillCertInfo(USE_INTERNAL_PKCS10, certInfo, authToken, httpParams); + + } + + public void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + + PKCS10 p10 = null; + + CMS.debug("PKCS10Processor:fillCertInfo"); + + if (protocolString == null) { + p10 = getPKCS10(httpParams); + } else if (protocolString.equals(USE_INTERNAL_PKCS10)) { + p10 = mPkcs10; + } else { + CMS.debug("PKCS10Processor::fillCertInfo() - p10 is null!"); + throw new EBaseException("p10 is null"); + } + + if (mServlet == null) { + EBaseException ex = new ECMSGWException("Servlet property of PKCS10Processor is null."); + + throw ex; + + } + + // fill key + X509Key key = p10.getSubjectPublicKeyInfo(); + + if (key == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_MISSING_KEY_IN_P10")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_KEY_IN_P10")); + } + CertificateX509Key certKey = new CertificateX509Key(key); + + try { + certInfo.set(X509CertInfo.KEY, certKey); + } catch (CertificateException e) { + EBaseException ex = new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + + log(ILogger.LL_FAILURE, ex.toString()); + throw ex; + } catch (IOException e) { + EBaseException ex = new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + + log(ILogger.LL_FAILURE, ex.toString()); + throw ex; + } + + X500Name subject = p10.getSubjectName(); + + if (subject != null) { + try { + certInfo.set(X509CertInfo.SUBJECT, + new CertificateSubjectName(subject)); + log(ILogger.LL_INFO, + "Setting subject name " + subject + " from p10."); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString())); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString())); + } catch (Exception e) { + // if anything bad happens in X500 name parsing, + // this will catch it. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_SUBJECT_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_FROM_P10_FAILED", e.toString())); + } + } else if (authToken == null || + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_SUBJECT_IN_P10")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_IN_P10")); + } + + // fill extensions from pkcs 10 attributes if any. + // other pkcs10 attributes are not recognized. + // ExtensionReq ::= SEQUENCE OF Extension + // ExtensionReq {pkcs-9 14}. + try { + PKCS10Attributes p10Attrs = p10.getAttributes(); + + if (p10Attrs != null) { + PKCS10Attribute p10Attr = (PKCS10Attribute) + (p10Attrs.getAttribute(CertificateExtensions.NAME)); + + if (p10Attr != null && p10Attr.getAttributeId().equals( + PKCS9Attribute.EXTENSION_REQUEST_OID)) { + Extensions exts0 = (Extensions) + (p10Attr.getAttributeValue()); + DerOutputStream extOut = new DerOutputStream(); + + exts0.encode(extOut); + byte[] extB = extOut.toByteArray(); + DerInputStream extIn = new DerInputStream(extB); + CertificateExtensions exts = new CertificateExtensions(extIn); + + if (exts != null) { + certInfo.set(X509CertInfo.EXTENSIONS, exts); + } + } + } + CMS.debug( + "PKCS10Processor: Seted cert extensions from pkcs10. "); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + } catch (Exception e) { + // if anything bad happens in extensions parsing, + // this will catch it. + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_FAILED_SET_EXTENSIONS_FROM_P10", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_KEY_FROM_P10_FAILED", e.toString())); + } + + // override pkcs10 attributes with authtoken attributes + // like subject name, validity and extensions if any. + // adminEnroll is an exception + String authMgr = mServlet.getAuthMgr(); + + if (authToken != null && + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT) != null && + !(authMgr.equals(IAuthSubsystem.PASSWDUSERDB_AUTHMGR_ID))) { + fillCertInfoFromAuthToken(certInfo, authToken); + } + + // SPECIAL CASE: + // if it is adminEnroll servlet, get the validity + // from the http parameters. + if (mServletId.equals(PKIProcessor.ADMIN_ENROLL_SERVLET_ID)) { + fillValidityFromForm(certInfo, httpParams); + } + + } + + private PKCS10 getPKCS10(IArgBlock httpParams) + throws EBaseException { + + PKCS10 pkcs10 = null; + + String certType = null; + + // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType + // instead of certType + certType = httpParams.getValueAsString(PKIProcessor.OLD_CERT_TYPE, null); + if (certType == null) { + certType = httpParams.getValueAsString(PKIProcessor.CERT_TYPE, "client"); + } else { + // some policies may rely on the fact that + // CERT_TYPE is set. So for 3.5.1 or eariler + // we need to set CERT_TYPE but not here. + } + if (certType.equals("client")) { + // coming from MSIE + String p10b64 = httpParams.getValueAsString(PKIProcessor.PKCS10_REQUEST, null); + + if (p10b64 != null) { + try { + byte[] bytes = CMS.AtoB(p10b64); + + pkcs10 = new PKCS10(bytes); + } catch (Exception e) { + // ok, if the above fails, it could + // be a PKCS10 with header + pkcs10 = httpParams.getValueAsPKCS10(PKIProcessor.PKCS10_REQUEST, false, null); + // e.printStackTrace(); + } + } + + //pkcs10 = httpParams.getValuePKCS10(PKCS10_REQUEST, null); + + } else { + try { + // coming from server cut & paste blob. + pkcs10 = httpParams.getValueAsPKCS10(PKIProcessor.PKCS10_REQUEST, false, null); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + return pkcs10; + + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/processors/PKIProcessor.java b/base/common/src/com/netscape/cms/servlet/processors/PKIProcessor.java new file mode 100644 index 000000000..5b78bb42a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/processors/PKIProcessor.java @@ -0,0 +1,356 @@ +// --- 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.processors; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.util.Date; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Process Certificate Requests + * + * @version $Revision$, $Date$ + */ +public class PKIProcessor implements IPKIProcessor { + + public final static String ADMIN_ENROLL_SERVLET_ID = "caadminEnroll"; + public static final String SUBJECT_NAME = "subject"; + public static final String OLD_CERT_TYPE = "csrCertType"; + public static final String CERT_TYPE = "certType"; + public static final String PKCS10_REQUEST = "pkcs10Request"; + public static final String SUBJECT_KEYGEN_INFO = "subjectKeyGenInfo"; + + protected CMSRequest mRequest = null; + + protected HttpServletRequest httpReq = null; + protected String mServletId = null; + protected CMSServlet mServlet = null; + + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + + public PKIProcessor() { + } + + public PKIProcessor(CMSRequest cmsReq, CMSServlet servlet) { + mRequest = cmsReq; + + mServlet = servlet; + + if (mServlet == null || mRequest == null) { + return; + } + + mServletId = servlet.getId(); + + } + + public void process(CMSRequest cmsReq) + throws EBaseException { + } + + protected void fillCertInfo( + String protocolString, X509CertInfo certInfo, + IAuthToken authToken, IArgBlock httpParams) + throws EBaseException { + } + + protected X509CertInfo[] fillCertInfoArray( + String protocolString, IAuthToken authToken, IArgBlock httpParams, IRequest req) + throws EBaseException { + return null; + } + + /** + * fill subject name, validity, extensions from authoken if any, + * overriding what was in pkcs10. + * fill subject name, extensions from http input if not authenticated. + * requests not authenticated will need to be approved by an agent. + */ + public static void fillCertInfoFromAuthToken( + X509CertInfo certInfo, IAuthToken authToken) + throws EBaseException { + // override subject, validity and extensions from auth token + // CA determines algorithm, version and issuer. + // take key from keygen, cmc, pkcs10 or crmf. + + CMS.debug("PKIProcessor: fillCertInfoFromAuthToken"); + // subject name. + try { + String subjectname = + authToken.getInString(AuthToken.TOKEN_CERT_SUBJECT); + + if (subjectname != null) { + CertificateSubjectName certSubject = (CertificateSubjectName) + new CertificateSubjectName(new X500Name(subjectname)); + + certInfo.set(X509CertInfo.SUBJECT, certSubject); + log(ILogger.LL_INFO, + "cert subject set to " + certSubject + " from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME", + e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } + + // validity + try { + CertificateValidity validity = null; + Date notBefore = + authToken.getInDate(AuthToken.TOKEN_CERT_NOTBEFORE); + Date notAfter = + authToken.getInDate(AuthToken.TOKEN_CERT_NOTAFTER); + + if (notBefore != null && notAfter != null) { + validity = new CertificateValidity(notBefore, notAfter); + certInfo.set(X509CertInfo.VALIDITY, validity); + log(ILogger.LL_INFO, + "cert validity set to " + validity + " from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_VALIDITY_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_VALIDITY_ERROR")); + } + + // extensions + try { + CertificateExtensions extensions = + authToken.getInCertExts(X509CertInfo.EXTENSIONS); + + if (extensions != null) { + certInfo.set(X509CertInfo.EXTENSIONS, extensions); + log(ILogger.LL_INFO, "cert extensions set from authtoken"); + } + } catch (CertificateException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR")); + } catch (IOException e) { + log(ILogger.LL_WARN, + CMS.getLogMessage("CMSGW_ERROR_SET_EXTENSIONS_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_EXTENSIONS_ERROR")); + } + } + + /** + * fill subject name, extension from form. + * this is done for unauthenticated requests. + * unauthenticated requests must be approved by agents so these will + * all be seen by and agent. + */ + public static void fillCertInfoFromForm( + X509CertInfo certInfo, IArgBlock httpParams) + throws EBaseException { + + CMS.debug("PKIProcessor: fillCertInfoFromForm"); + // subject name. + try { + String subject = httpParams.getValueAsString(PKIProcessor.SUBJECT_NAME, null); + + if (subject == null) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_SUBJECT_FROM_FORM")); + } + + X500Name x500name = new X500Name(subject); + + certInfo.set( + X509CertInfo.SUBJECT, new CertificateSubjectName(x500name)); + + fillValidityFromForm(certInfo, httpParams); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IllegalArgumentException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_REQ_ILLEGAL_CHARACTERS")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CONVERT_DN_TO_X500NAME_ERROR")); + } + + // requested extensions. + // let polcies form extensions from http input. + } + + public static void fillValidityFromForm( + X509CertInfo certInfo, IArgBlock httpParams) + throws EBaseException { + CMS.debug("PKIProcessor: fillValidityFromForm!"); + try { + String notValidBeforeStr = httpParams.getValueAsString("notValidBefore", null); + String notValidAfterStr = httpParams.getValueAsString("notValidAfter", null); + + if (notValidBeforeStr != null && notValidAfterStr != null) { + long notValidBefore = 0; + long notValidAfter = 0; + + try { + notValidBefore = Long.parseLong(notValidBeforeStr); + } catch (NumberFormatException e) { + } + try { + notValidAfter = Long.parseLong(notValidAfterStr); + } catch (NumberFormatException e) { + } + + if (notValidBefore > 0 && notValidAfter > 0) { + CertificateValidity validity = null; + Date notBefore = new Date(notValidBefore); + Date notAfter = new Date(notValidAfter); + + if (notBefore != null && notAfter != null) { + validity = new CertificateValidity(notBefore, notAfter); + certInfo.set(X509CertInfo.VALIDITY, validity); + log(ILogger.LL_INFO, + "cert validity set to " + validity + " from authtoken"); + } + } + } + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_SET_SUBJECT_NAME_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_SET_SUBJECT_NAME_ERROR")); + } + } + + /** + * log according to authority category. + */ + public static void log(int event, int level, String msg) { + CMS.getLogger().log(event, ILogger.S_OTHER, level, + "PKIProcessor " + ": " + msg); + } + + public static void log(int level, String msg) { + CMS.getLogger().log(ILogger.EV_SYSTEM, ILogger.S_OTHER, level, + "PKIProcessor " + ": " + msg); + } + + /** + * Signed Audit Log + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to store messages to the signed audit log. + * <P> + * + * @param msg signed audit log message + */ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (mSignedAuditLogger == null) { + return; + } + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Subject ID + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to obtain the "SubjectID" for + * a signed audit log message. + * <P> + * + * @return id string containing the signed audit log message SubjectID + */ + protected String auditSubjectID() { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String subjectID = null; + + // Initialize subjectID + SessionContext auditContext = SessionContext.getExistingContext(); + + if (auditContext != null) { + subjectID = (String) + auditContext.get(SessionContext.USER_ID); + + if (subjectID != null) { + subjectID = subjectID.trim(); + } else { + subjectID = ILogger.NONROLEUSER; + } + } else { + subjectID = ILogger.UNIDENTIFIED; + } + + return subjectID; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java new file mode 100644 index 000000000..48848695f --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java @@ -0,0 +1,532 @@ +// --- 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.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +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.EProfileException; +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfilePolicy; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.cms.servlet.common.CMSRequest; + +/** + * Toggle the approval state of a profile + * + * @version $Revision$, $Date$ + */ +public class ProfileApproveServlet extends ProfileServlet { + + /** + * + */ + private static final long serialVersionUID = 3956879326742839550L; + 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. + * <P> + * + * <ul> + * <li>http.param profileId the id of the profile to change + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL used when an agent approves/disapproves a cert + * profile set by the administrator for automatic approval + * </ul> + * + * @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); + auditSubjectID = auditSubjectID(); + CMS.debug("uid=" + authToken.getInString("userid")); + userid = authToken.getInString("userid"); + } catch (Exception e) { + auditSubjectID = auditSubjectID(); + 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<String> policySetIds = profile.getProfilePolicySetIds(); + + ArgList setlist = new ArgList(); + + while (policySetIds.hasMoreElements()) { + String setId = policySetIds.nextElement(); + + Enumeration<String> policyIds = profile.getProfilePolicyIds(setId); + ArgList list = new ArgList(); + + while (policyIds.hasMoreElements()) { + String id = policyIds.nextElement(); + IProfilePolicy policy = 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<String> defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = 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. + * <P> + * + * @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. + * <P> + * + * @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/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java new file mode 100644 index 000000000..2ca5f0a5c --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java @@ -0,0 +1,176 @@ +// --- 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.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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 long serialVersionUID = -5118812083812548395L; + + 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<String> 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/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java new file mode 100644 index 000000000..e482b67da --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java @@ -0,0 +1,960 @@ +// --- 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.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EDeferException; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.ERejectException; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileOutput; +import com.netscape.certsrv.profile.IProfilePolicy; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.property.EPropertyException; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.profile.common.ProfilePolicy; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.util.Utils; + +/** + * This servlet approves profile-based request. + * + * @version $Revision$, $Date$ + */ +public class ProfileProcessServlet extends ProfileServlet { + /** + * + */ + private static final long serialVersionUID = 5244627530516577838L; + 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 + * <P> + * + * (Certificate Request Processed - a manual "agent" profile based cert cancellation) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @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 + * <P> + * + * (Certificate Request Processed - a manual "agent" profile based cert rejection) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @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 + * <P> + * + * (Certificate Request Processed - a manual "agent" profile based cert acceptance) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @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<String> outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput( + outputId); + + Enumeration<String> outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = + 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<ProfilePolicy> policies = profile.getProfilePolicies(profileSetId); + int count = 0; + + while (policies.hasMoreElements()) { + ProfilePolicy policy = policies.nextElement(); + + setValue(locale, count, policy, req, request); + count++; + } + + policies = profile.getProfilePolicies(profileSetId); + count = 0; + while (policies.hasMoreElements()) { + ProfilePolicy policy = 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<String> defNames = def.getValueNames(); + + while (defNames.hasMoreElements()) { + String defName = 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. + * <P> + * + * @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. + * <P> + * + * @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. + * <P> + * + * @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 = Utils.base64encode(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/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java new file mode 100644 index 000000000..dd0ee7be7 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java @@ -0,0 +1,455 @@ +// --- 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 java.util.Random; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.Nonces; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.profile.IProfileOutput; +import com.netscape.certsrv.profile.IProfilePolicy; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.property.EPropertyException; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.cms.servlet.common.CMSRequest; + +/** + * This servlet allows reviewing of profile-based request. + * + * @version $Revision$, $Date$ + */ +public class ProfileReviewServlet extends ProfileServlet { + + /** + * + */ + private static final long serialVersionUID = -6559751428547928511L; + + 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. + * <ul> + * <li>http.param requestId the ID of the profile to review + * </ul> + * + * @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<String> policyIds = (profileSetId != null && profileSetId.length() > 0) ? + profile.getProfilePolicyIds(profileSetId) : null; + ArgList list = new ArgList(); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = policyIds.nextElement(); + IProfilePolicy policy = + 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); + } + } + + 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + + Enumeration<String> inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + ArgSet inputset = new ArgSet(); + String inputName = 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<String> outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId + ); + + Enumeration<String> outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = 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<String> defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = 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/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java new file mode 100644 index 000000000..5b07951f8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java @@ -0,0 +1,411 @@ +// --- 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.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +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.EProfileException; +import com.netscape.certsrv.profile.IPolicyConstraint; +import com.netscape.certsrv.profile.IPolicyDefault; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.profile.IProfilePolicy; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.cms.servlet.common.CMSRequest; + +/** + * Retrieve detailed information of a particular profile. + * + * @version $Revision$, $Date$ + */ +public class ProfileSelectServlet extends ProfileServlet { + + /** + * + */ + private static final long serialVersionUID = -3765390650830903602L; + 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. + * <ul> + * <li>http.param profileId the id of the profile to select + * </ul> + * + * @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<String> policySetIds = profile.getProfilePolicySetIds(); + + if (policySetIds != null) { + while (policySetIds.hasMoreElements()) { + String setId = policySetIds.nextElement(); + + ArgList list = new ArgList(); + Enumeration<String> policyIds = profile.getProfilePolicyIds(setId); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = 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<String> authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + ArgSet authset = new ArgSet(); + String authName = 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = 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<String> inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + ArgSet inputset = new ArgSet(); + String inputName = 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<String> defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = 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<String> conNames = con.getConfigNames(); + if (conNames != null) { + while (conNames.hasMoreElements()) { + ArgSet conset = new ArgSet(); + String conName = 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/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java new file mode 100644 index 000000000..457b8422b --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java @@ -0,0 +1,511 @@ +// --- 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.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authorization.IAuthzSubsystem; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.certsrv.template.ArgString; +import com.netscape.certsrv.template.IArgValue; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.base.UserInfo; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.ServletUtils; + +/** + * This servlet is the base class of all profile servlets. + * + * @version $Revision$, $Date$ + */ +public class ProfileServlet extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -7011378748671762375L; + 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 = ServletUtils.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("<list>"); + for (int i = 0; i < list.size(); i++) { + outputArgValueAsXML(ps, name, list.get(i)); + } + ps.println("</list>"); + } 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("<set>"); + Enumeration<String> names = set.getNames(); + while (names.hasMoreElements()) { + String n = names.nextElement(); + outputArgValueAsXML(ps, n, set.get(n)); + } + ps.println("</set>"); + } else { + ps.println(v); + } + } + ps.println("</" + name + ">"); + } + + protected void outputThisAsXML(ByteArrayOutputStream bos, ArgSet args) { + PrintStream ps = new PrintStream(bos); + ps.println("<xml>"); + outputArgValueAsXML(ps, "output", args); + ps.println("</xml>"); + 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("<CMS_TEMPLATE>") == -1) { + writer.println(line); + } else { + // output javascript parameters + writer.println("<script type=\"text/javascript\">"); + outputData(writer, args); + writer.println("</script>"); + } + } + } 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) && (c != 0x3c) && (c != 0x3e)) { + out[j++] = c; + continue; + } + + /* some inputs are coming in as '\' and 'n' */ + /* see BZ 500736 for details */ + if ((c == 0x5c) && ((i + 1) < l) && (in[i + 1] == 'n' || + in[i + 1] == 'r' || in[i + 1] == 'f' || in[i + 1] == 't' || + in[i + 1] == '<' || in[i + 1] == '>' || + in[i + 1] == '\"' || in[i + 1] == '\'' || in[i + 1] == '\\')) { + if (in[i + 1] == 'x' && ((i + 3) < l) && in[i + 2] == '3' && + (in[i + 3] == 'c' || in[i + 3] == 'e')) { + out[j++] = '\\'; + out[j++] = in[i + 1]; + out[j++] = in[i + 2]; + out[j++] = in[i + 3]; + i += 3; + } else { + out[j++] = '\\'; + out[j++] = in[i + 1]; + i++; + } + continue; + } + + switch (c) { + case '\n': + out[j++] = '\\'; + out[j++] = 'n'; + break; + + case '\\': + out[j++] = '\\'; + out[j++] = '\\'; + break; + + case '\"': + out[j++] = '\\'; + out[j++] = '\"'; + break; + + case '\r': + out[j++] = '\\'; + out[j++] = 'r'; + break; + + case '\f': + out[j++] = '\\'; + out[j++] = 'f'; + break; + + case '\t': + out[j++] = '\\'; + out[j++] = 't'; + break; + + case '<': + out[j++] = '\\'; + out[j++] = 'x'; + out[j++] = '3'; + out[j++] = 'c'; + break; + + case '>': + 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<String> e = set.getNames(); + + while (e.hasMoreElements()) { + String n = 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<String> e = set.getNames(); + + while (e.hasMoreElements()) { + String n = 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/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java new file mode 100644 index 000000000..16451f6dd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java @@ -0,0 +1,904 @@ +// --- 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.InputStream; +import java.io.OutputStream; +import java.security.cert.CertificateEncodingException; +import java.util.Enumeration; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.X509CertImpl; + +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.asn1.UTF8String; +import org.mozilla.jss.pkix.cmc.LraPopWitness; +import org.mozilla.jss.pkix.cmc.OtherInfo; +import org.mozilla.jss.pkix.cmc.TaggedAttribute; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EDeferException; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.ERejectException; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileContext; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.request.INotify; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cms.servlet.common.CMCOutputTemplate; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.util.Utils; + +/** + * This servlet submits end-user request into the profile framework. + * + * @version $Revision$, $Date$ + */ +public class ProfileSubmitCMCServlet extends ProfileServlet { + + /** + * + */ + private static final long serialVersionUID = -8017841111435988197L; + 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + ctx.set(inputName, request.getParameter(inputName)); + } + } + } + } + + } + + private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, + IProfileContext ctx) { + Enumeration<String> authIds = authenticator.getValueNames(); + + if (authIds != null) { + while (authIds.hasMoreElements()) { + String authName = 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<String> authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + String inputName = inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + req.setExtData(inputName, request.getParameter(inputName)); + } + } + } + } + } + } + + /** + * Process the HTTP request + * <P> + * + * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE" + * profile based cert rejection) + * <P> + * + * <ul> + * <li>http.param profileId ID of profile to use to process request + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @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); + 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 = Utils.base64encode(reqbuf); + + if (CMS.debugOn()) { + CMS.debug("Start of ProfileSubmitCMCServlet Input Parameters"); + @SuppressWarnings("unchecked") + Enumeration<String> paramNames = request.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String paramName = 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<String> tokenNames = authToken.getElements(); + while (tokenNames.hasMoreElements()) { + String tokenName = 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; + + 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<String> reqKeys = reqs[k].getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = 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 { + SessionContext.releaseContext(); + } + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @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. + * <P> + * + * @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 = Utils.base64encode(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/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java new file mode 100644 index 000000000..eb3b93eb8 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java @@ -0,0 +1,1631 @@ +// --- 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.math.BigInteger; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import org.w3c.dom.Node; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.MetaInfo; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.EDeferException; +import com.netscape.certsrv.profile.EProfileException; +import com.netscape.certsrv.profile.ERejectException; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileAuthenticator; +import com.netscape.certsrv.profile.IProfileContext; +import com.netscape.certsrv.profile.IProfileInput; +import com.netscape.certsrv.profile.IProfileOutput; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.property.IDescriptor; +import com.netscape.certsrv.request.INotify; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.certsrv.util.IStatsSubsystem; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cmsutil.util.Cert; +import com.netscape.cmsutil.util.Utils; +import com.netscape.cmsutil.xml.XMLObject; + +/** + * 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 long serialVersionUID = 7557922703180866442L; + 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"; + + private final static String LOGGING_SIGNED_AUDIT_AUTH_FAIL = + "LOGGING_SIGNED_AUDIT_AUTH_FAIL_4"; + private final static String LOGGING_SIGNED_AUDIT_AUTH_SUCCESS = + "LOGGING_SIGNED_AUDIT_AUTH_SUCCESS_3"; + + 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> 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<String> 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<String> 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> 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<String> inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration<String> 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<String> outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId); + + Enumeration<String> 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 + * <P> + * + * (Certificate Request Processed - either an automated "EE" profile based cert acceptance, or an automated "EE" + * profile based cert rejection) + * <P> + * + * <ul> + * <li>http.param profileId ID of profile to use to process request + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @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 */); + } + + Locale locale = getLocale(request); + ArgSet args = new ArgSet(); + + if (CMS.debugOn()) { + CMS.debug("Start of ProfileSubmitServlet Input Parameters"); + @SuppressWarnings("unchecked") + Enumeration<String> paramNames = request.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String paramName = 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<String> 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) { + + CMS.debug("ProfileSubmitServlet: authentication required."); + String uid_cred = "Unidentified"; + String uid_attempted_cred = "Unidentified"; + Enumeration<String> authIds = authenticator.getValueNames(); + //Attempt to possibly fetch attemped uid, may not always be available. + if (authIds != null) { + while (authIds.hasMoreElements()) { + String authName = authIds.nextElement(); + String value = request.getParameter(authName); + if (value != null) { + if (authName.equals("uid")) { + uid_attempted_cred = value; + } + } + } + } + + String authSubjectID = auditSubjectID(); + + String authMgrID = authenticator.getName(); + String auditMessage = 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"); + } + + //audit log our authentication failure + + authSubjectID += " : " + uid_cred; + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_FAIL, + authSubjectID, + ILogger.FAILURE, + authMgrID, + uid_attempted_cred); + audit(auditMessage); + + return; + } + + //Log successful authentication + + //Attempt to get uid from authToken, most tokens respond to the "uid" cred. + uid_cred = authToken.getInString("uid"); + + if (uid_cred == null || uid_cred.length() == 0) { + uid_cred = "Unidentified"; + } + + authSubjectID = authSubjectID + " : " + uid_cred; + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_AUTH_SUCCESS, + authSubjectID, + ILogger.SUCCESS, + authMgrID); + + audit(auditMessage); + + } + 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 { + String resource = profileId + ".authz.acl"; + authorize(mAclMethod, resource, 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<String> tokenNames = authToken.getElements(); + while (tokenNames.hasMoreElements()) { + String tokenName = 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<String> reqKeys = reqs[k].getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = 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 { + SessionContext.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 < reqs.length; i++) { + Node subnode = xmlObj.createContainer(n, "Request"); + xmlObj.addItemToContainer(subnode, "Id", reqs[i].getRequestId().toString()); + X509CertInfo certInfo = + reqs[i].getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO); + if (certInfo != null) { + String subject = ""; + subject = (String) certInfo.get(X509CertInfo.SUBJECT).toString(); + xmlObj.addItemToContainer(subnode, "SubjectDN", subject); + } else { + CMS.debug("ProfileSubmitServlet xmlOutput: no certInfo found in request"); + } + Enumeration<String> outputIds = profile.getProfileOutputIds(); + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId); + Enumeration<String> outputNames = profileOutput.getValueNames(); + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + String outputName = outputNames.nextElement(); + if (!outputName.equals("b64_cert") && !outputName.equals("pkcs7")) + continue; + try { + String outputValue = profileOutput.getValue(outputName, locale, reqs[i]); + if (outputName.equals("b64_cert")) { + String ss = Cert.normalizeCertStrAndReq(outputValue); + outputValue = Cert.stripBrackets(ss); + byte[] bcode = CMS.AtoB(outputValue); + X509CertImpl impl = new X509CertImpl(bcode); + xmlObj.addItemToContainer(subnode, + "serialno", impl.getSerialNumber().toString(16)); + xmlObj.addItemToContainer(subnode, "b64", outputValue); + }// if b64_cert + else if (outputName.equals("pkcs7")) { + String ss = Cert.normalizeCertStrAndReq(outputValue); + xmlObj.addItemToContainer(subnode, "pkcs7", ss); + } + + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet xmlOutput: " + e.toString()); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet xmlOutput: " + e.toString()); + } + } + } + } + } + } + + byte[] cb = xmlObj.toByteArray(); + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <P> + * + * @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. + * <P> + * + * @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 = Utils.base64encode(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/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java b/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java new file mode 100644 index 000000000..0114f6323 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java @@ -0,0 +1,39 @@ +// --- 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.security.cert.X509Certificate; + +import javax.servlet.http.HttpServletRequest; + +import com.netscape.certsrv.authentication.ISSLClientCertProvider; + +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; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java b/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java new file mode 100644 index 000000000..d8fc68a69 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java @@ -0,0 +1,925 @@ +// --- 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.request; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.lang.reflect.Array; +import java.math.BigInteger; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.CRLExtensions; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.Extension; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.IPrettyPrintFormat; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.RawJS; + +/** + * Output a 'pretty print' of a certificate request + * + * @version $Revision$, $Date$ + */ +public class CertReqParser extends ReqParser { + + public static final CertReqParser DETAIL_PARSER = new CertReqParser(true); + public static final CertReqParser NODETAIL_PARSER = new CertReqParser(false); + + private boolean mDetails = true; + private IPrettyPrintFormat pp = null; + + /** + * Constructs a certificate request parser. + */ + public CertReqParser() { + pp = CMS.getPrettyPrintFormat(":"); + } + + /** + * Constructs a certificate request parser. + * + * @param details return detailed information (this can be time consuming) + */ + public CertReqParser(boolean details) { + mDetails = details; + pp = CMS.getPrettyPrintFormat(":"); + } + + private static final String EXT_PRETTYPRINT = "ext_prettyprint"; + + private static final String DOT = "."; + private static final String LB = "["; + private static final String RB = "]"; + private static final String EQ = " = "; + + private static final String HTTP_PARAMS_COUNTER = IRequest.HTTP_PARAMS + LB + "httpParamsCount++" + RB; + private static final String HTTP_HEADERS_COUNTER = IRequest.HTTP_HEADERS + LB + "httpHeadersCount++" + RB; + private static final String AUTH_TOKEN_COUNTER = IRequest.AUTH_TOKEN + LB + "authTokenCount++" + RB; + private static final String SERVER_ATTRS_COUNTER = IRequest.SERVER_ATTRS + LB + "serverAttrsCount++" + RB; + + /** + * Fills in certificate specific request attributes. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + if (req.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null) { + fillX509RequestIntoArg(l, req, argSet, arg); + } else if (req.getExtDataInRevokedCertArray(IRequest.CERT_INFO) != null) { + fillRevokeRequestIntoArg(l, req, argSet, arg); + } else { + //o = req.get(IRequest.OLD_CERTS); + //if (o != null) + fillRevokeRequestIntoArg(l, req, argSet, arg); + } + } + + private void fillX509RequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + + // fill in the standard attributes + super.fillRequestIntoArg(l, req, argSet, arg); + + arg.addStringValue("certExtsEnabled", "yes"); + + int saCounter = 0; + Enumeration<String> enum1 = req.getExtDataKeys(); + + // gross hack + String prefix = "record."; + + if (argSet.getHeader() == arg) + prefix = "header."; + + while (enum1.hasMoreElements()) { + String name = enum1.nextElement(); + + if (mDetails) { + // show all http parameters stored in request. + if (name.equalsIgnoreCase(IRequest.HTTP_PARAMS)) { + Hashtable<String, String> http_params = req.getExtDataInHashtable(name); + // show certType specially + String certType = http_params.get(IRequest.CERT_TYPE); + + if (certType != null) { + arg.addStringValue(IRequest.CERT_TYPE, certType); + } + String presenceServerExt = (String) http_params.get("PresenceServerExtension"); + + if (presenceServerExt != null) { + arg.addStringValue("PresenceServerExtension", presenceServerExt); + } + // show all http parameters in request + int counter = 0; + Enumeration<String> elms = http_params.keys(); + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_PARAMS + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_params.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all http headers stored in request. + else if (name.equalsIgnoreCase(IRequest.HTTP_HEADERS)) { + Hashtable<String, String> http_hdrs = req.getExtDataInHashtable(name); + Enumeration<String> elms = http_hdrs.keys(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_HEADERS + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_hdrs.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all auth token stored in request. + else if (name.equalsIgnoreCase(IRequest.AUTH_TOKEN)) { + IAuthToken auth_token = req.getExtDataInAuthToken(name); + Enumeration<String> elms = auth_token.getElements(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.AUTH_TOKEN + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + Object authTokenValue = auth_token.getInStringArray(n); + if (authTokenValue == null) { + authTokenValue = auth_token.getInString(n); + } + String v = expandValue(prefix + parami + ".value", + authTokenValue); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n" + v; + + arg.set(parami, new RawJS(rawJS)); + } + } // all others are request attrs from policy or internal modules. + else { + Object val; + if (req.isSimpleExtDataValue(name)) { + val = req.getExtDataInString(name); + } else { + val = req.getExtDataInStringArray(name); + if (val == null) { + val = req.getExtDataInHashtable(name); + } + } + String valstr = ""; + // hack + String parami = + IRequest.SERVER_ATTRS + LB + String.valueOf(saCounter++) + RB; + + if (name.equalsIgnoreCase(IRequest.ISSUED_CERTS) && mDetails && + (req.getRequestStatus().toString().equals(RequestStatus.COMPLETE_STRING) || + req.getRequestType().equals(IRequest.GETREVOCATIONINFO_REQUEST))) { + X509CertImpl issuedCert[] = + req.getExtDataInCertArray(IRequest.ISSUED_CERTS); + if (issuedCert != null && issuedCert[0] != null) { + val = "<pre>" + CMS.getCertPrettyPrint(issuedCert[0]).toString(l) + "</pre>"; + } + } else if (name.equalsIgnoreCase(IRequest.CERT_INFO) && mDetails) { + X509CertInfo[] certInfo = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + if (certInfo != null && certInfo[0] != null) { + val = "<pre>" + certInfo[0].toString() + "</pre>"; + } + } + + valstr = expandValue(prefix + parami + ".value", val); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(name) + "\";\n" + + valstr; // java string already escaped in expandValue. + + arg.set(parami, new RawJS(rawJS)); + } + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_PHONE) + || name.equalsIgnoreCase(IRequest.REQUESTOR_EMAIL) + || name.equalsIgnoreCase(IRequest.REQUESTOR_COMMENTS) + || name.equalsIgnoreCase(IRequest.RESULT) + || name.equalsIgnoreCase(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE)) { + arg.addStringValue(name, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_NAME)) { + String requestorName = req.getExtDataInString(name); + + requestorName = requestorName.trim(); + if (requestorName.length() > 0) { + arg.addStringValue(name, requestorName); + } + } + + if (name.equalsIgnoreCase(IRequest.ERRORS)) { + Vector<String> errorStrings = req.getExtDataInStringVector(name); + if (errorStrings != null) { + StringBuffer errInfo = new StringBuffer(); + + for (int i = 0; i < errorStrings.size(); i++) { + errInfo.append(errorStrings.elementAt(i)); + errInfo.append("\n"); + } + arg.addStringValue(IRequest.ERRORS, errInfo.toString()); + } + } + if (name.equalsIgnoreCase(IRequest.ERROR)) { + arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.CERT_INFO)) { + // Get the certificate info from the request + X509CertInfo[] certInfo = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + if (certInfo != null && certInfo[0] != null) { + // Get the subject name if any set. + CertificateSubjectName subjectName = null; + String signatureAlgorithm = null; + String signatureAlgorithmName = null; + + try { + subjectName = (CertificateSubjectName) certInfo[0].get(X509CertInfo.SUBJECT); + } catch (IOException e) { + // XXX raise exception + } catch (CertificateException e) { + // XXX raise exception + } + if (subjectName != null) { + String sn; + + try { + sn = subjectName.toString(); + } catch (java.lang.IllegalArgumentException e) { + sn = "* * Malformed Subject Name * *"; + } + String subjectnamevalue = sn; + + arg.addStringValue("subject", subjectnamevalue); + } + + if (mDetails) { + try { + CertificateAlgorithmId certAlgId = (CertificateAlgorithmId) + certInfo[0].get(X509CertInfo.ALGORITHM_ID); + AlgorithmId algId = (AlgorithmId) + certAlgId.get(CertificateAlgorithmId.ALGORITHM); + + signatureAlgorithm = (algId.getOID()).toString(); + signatureAlgorithmName = algId.getName(); + } catch (Exception e) { + // XXX raise exception + } + if (signatureAlgorithm != null) { + arg.addStringValue("signatureAlgorithm", signatureAlgorithm); + } + if (signatureAlgorithmName != null) { + arg.addStringValue("signatureAlgorithmName", signatureAlgorithmName); + } + + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) certInfo[0].get(X509CertInfo.EXTENSIONS); + } catch (Exception e) { + } + if (extensions != null) { + Enumeration<Extension> exts = extensions.getAttributes(); + + while (exts.hasMoreElements()) { + Extension ext = exts.nextElement(); + + // only know about ns cert type + if (ext instanceof NSCertTypeExtension) { + NSCertTypeExtension nsExtensions = + (NSCertTypeExtension) ext; + + try { + arg.addStringValue("ext_" + NSCertTypeExtension.SSL_SERVER, + nsExtensions.get(NSCertTypeExtension.SSL_SERVER).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.SSL_CLIENT, + nsExtensions.get(NSCertTypeExtension.SSL_CLIENT).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.EMAIL, + nsExtensions.get(NSCertTypeExtension.EMAIL).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.OBJECT_SIGNING, + nsExtensions.get(NSCertTypeExtension.OBJECT_SIGNING).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.SSL_CA, + nsExtensions.get(NSCertTypeExtension.SSL_CA).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.EMAIL_CA, + nsExtensions.get(NSCertTypeExtension.EMAIL_CA).toString()); + + arg.addStringValue("ext_" + NSCertTypeExtension.OBJECT_SIGNING_CA, + nsExtensions.get(NSCertTypeExtension.OBJECT_SIGNING_CA).toString()); + + } catch (Exception e) { + } + } else if (ext instanceof BasicConstraintsExtension) { + BasicConstraintsExtension bcExt = + (BasicConstraintsExtension) ext; + Integer pathLength = null; + Boolean isCA = null; + + try { + pathLength = (Integer) bcExt.get(BasicConstraintsExtension.PATH_LEN); + isCA = (Boolean) bcExt.get(BasicConstraintsExtension.IS_CA); + } catch (IOException e) { + } + if (pathLength != null) + arg.addIntegerValue("pathLenBasicConstraints", pathLength.intValue()); + if (isCA != null) + arg.addBooleanValue("isCABasicConstraints", isCA.booleanValue()); + } // pretty print all others. + else { + if (argSet != null) { + IArgBlock rr = CMS.createArgBlock(); + + rr.addStringValue( + EXT_PRETTYPRINT, + CMS.getExtPrettyPrint(ext, 0).toString()); + argSet.addRepeatRecord(rr); + } + } + } + + } + + // Get the public key + CertificateX509Key certKey = null; + + try { + certKey = (CertificateX509Key) certInfo[0].get(X509CertInfo.KEY); + } catch (IOException e) { + // XXX raise exception + } catch (CertificateException e) { + // XXX raise exception + } + + X509Key key = null; + + try { + key = (X509Key) certKey.get(CertificateX509Key.KEY); + } catch (IOException e) { + // XXX raise exception + } + + if (key != null) { + arg.addStringValue("subjectPublicKeyInfo", + key.getAlgorithm() + " - " + key.getAlgorithmId().getOID().toString()); + arg.addStringValue("subjectPublicKey", + pp.toHexString(key.getKey(), 0, 16)); + } + + // Get the validity period + CertificateValidity validity = null; + + try { + validity = + (CertificateValidity) + certInfo[0].get(X509CertInfo.VALIDITY); + if (validity != null) { + long validityLength = (((Date) validity.get(CertificateValidity.NOT_AFTER)).getTime() - + ((Date) validity.get(CertificateValidity.NOT_BEFORE)).getTime()) / 1000; + arg.addLongValue("validityLength", validityLength); + } + } catch (IOException e) { + // XXX raise exception + } catch (CertificateException e) { + // XXX raise exception + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.OLD_SERIALS) && mDetails) { + BigInteger oldSerialNo[] = req.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS); + + if (oldSerialNo != null) { + if (argSet != null) { + for (int i = 0; i < oldSerialNo.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + oldSerialNo[i], 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.ISSUED_CERTS) && mDetails && + (req.getRequestStatus().toString().equals(RequestStatus.COMPLETE_STRING) || + req.getRequestType().equals(IRequest.GETREVOCATIONINFO_REQUEST))) { + X509CertImpl issuedCert[] = + req.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + arg.addBigIntegerValue("serialNumber", issuedCert[0].getSerialNumber(), 16); + // Set Serial No for 2nd certificate + if (issuedCert.length == 2) + arg.addBigIntegerValue("serialNumber2", issuedCert[1].getSerialNumber(), 16); + } + if (name.equalsIgnoreCase(IRequest.OLD_CERTS) && mDetails) { + X509CertImpl oldCert[] = + req.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (oldCert != null && oldCert.length > 0) { + arg.addBigIntegerValue("serialNumber", oldCert[0].getSerialNumber(), 16); + arg.addStringValue("subject", oldCert[0].getSubjectDN().toString()); + if (req.getRequestType().equals(IRequest.GETCERTS_REQUEST)) { + for (int i = 0; i < oldCert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + oldCert[i].getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.CACERTCHAIN) && mDetails) { + byte[] certChainData = req.getExtDataInByteArray( + IRequest.CACERTCHAIN); + if (certChainData != null) { + CertificateChain certChain = new CertificateChain(); + try { + certChain.decode(new ByteArrayInputStream(certChainData)); + + X509Certificate cert[] = certChain.getChain(); + + for (int i = 0; i < cert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert[i].getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + } catch (IOException e) { + // XXX + } + } + } + if (name.equalsIgnoreCase(IRequest.FINGERPRINTS) && mDetails) { + Hashtable<String, String> fingerprints = + req.getExtDataInHashtable(IRequest.FINGERPRINTS); + + if (fingerprints != null) { + String namesAndHashes = null; + Enumeration<String> enumFingerprints = fingerprints.keys(); + + while (enumFingerprints.hasMoreElements()) { + String hashname = enumFingerprints.nextElement(); + String hashvalue = fingerprints.get(hashname); + byte[] fingerprint = CMS.AtoB(hashvalue); + String ppFingerprint = pp.toHexString(fingerprint, 0); + + if (hashname != null && ppFingerprint != null) { + if (namesAndHashes != null) { + namesAndHashes += "+" + hashname + "+" + ppFingerprint; + } else { + namesAndHashes = hashname + "+" + ppFingerprint; + } + } + } + if (namesAndHashes != null) { + arg.addStringValue("fingerprints", namesAndHashes); + } + } + } + } + } + + /** + * print value out nicely in request attributes. + */ + protected String expandValue(String valuename, Object v) { + try { + String valstr = ""; + + // if it's a vector + if (v instanceof Vector) { + valstr = valuename + "= new Array"; + int j = 0; + + StringBuffer sb = new StringBuffer(); + for (@SuppressWarnings("unchecked") + Enumeration<String> n = ((Vector<String>) v).elements(); n.hasMoreElements(); j++) { + sb.append(";\n"); + sb.append(valuename); + sb.append(LB); + sb.append(j); + sb.append(RB); + sb.append(EQ); + sb.append("\""); + sb.append( + CMSTemplate.escapeJavaScriptStringHTML( + n.nextElement().toString())); + sb.append("\";\n"); + } + sb.append("\n"); + valstr = sb.toString(); + return valstr; + } + + // if an array. + int len = -1; + + try { + len = Array.getLength(v); + } catch (IllegalArgumentException e) { + } + if (len >= 0) { // is an array; access each object in array. + valstr = valuename + "= new Array"; + int i; + + for (i = 0; i < len; i++) { + if (Array.get(v, i) != null) + valstr += ";\n" + valuename + LB + i + RB + EQ + "\"" + + CMSTemplate.escapeJavaScriptStringHTML( + Array.get(v, i).toString()) + "\";\n"; + } + return valstr; + } + } catch (Throwable e) { + } + + // if string or unrecognized type, just call its toString method. + return valuename + "=\"" + + CMSTemplate.escapeJavaScriptStringHTML(v.toString()) + "\""; + } + + public String getRequestorDN(IRequest request) { + try { + X509CertInfo info = (X509CertInfo) + request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO); + // retrieve the subject name + CertificateSubjectName sn = (CertificateSubjectName) + info.get(X509CertInfo.SUBJECT); + + return sn.toString(); + } catch (Exception e) { + CMS.debug("CertReqParser: getRequestorDN " + e.toString()); + } + return null; + } + + public String getKeyID(IRequest request) { + try { + String kid = null; + + String cid = request.getExtDataInString(IRequest.NETKEY_ATTR_CUID); + if (cid == null) { + cid = ""; + } + String uid = request.getExtDataInString(IRequest.NETKEY_ATTR_USERID); + if (uid == null) { + uid = ""; + } + kid = cid + ":" + uid; + if (kid.equals(":")) { + kid = ""; + } + + return kid; + } catch (Exception e) { + CMS.debug("CertReqParser: getKeyID " + e.toString()); + } + return null; + } + + private void fillRevokeRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + // fill in the standard attributes + super.fillRequestIntoArg(l, req, argSet, arg); + + arg.addStringValue("certExtsEnabled", "yes"); + String profile = req.getExtDataInString("profile"); + + //CMS.debug("CertReqParser: profile=" + profile); + if (profile != null) { + arg.addStringValue("profile", profile); + String requestorDN = getRequestorDN(req); + + if (requestorDN != null) { + arg.addStringValue("subject", requestorDN); + } + } else { + arg.addStringValue("profile", "false"); + String keyID = getKeyID(req); + + if (keyID != null) { + arg.addStringValue("subject", keyID); + } + } + + int saCounter = 0; + Enumeration<String> enum1 = req.getExtDataKeys(); + + // gross hack + String prefix = "record."; + + if (argSet.getHeader() == arg) + prefix = "header."; + + while (enum1.hasMoreElements()) { + String name = (String) enum1.nextElement(); + + if (mDetails) { + // show all http parameters stored in request. + if (name.equalsIgnoreCase(IRequest.HTTP_PARAMS)) { + Hashtable<String, String> http_params = req.getExtDataInHashtable(name); + // show certType specially + String certType = http_params.get(IRequest.CERT_TYPE); + + if (certType != null) { + arg.addStringValue(IRequest.CERT_TYPE, certType); + } + // show all http parameters in request + int counter = 0; + Enumeration<String> elms = http_params.keys(); + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_PARAMS + LB + String.valueOf(counter++) + RB; + // hack + String n = (String) elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_params.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all http headers stored in request. + else if (name.equalsIgnoreCase(IRequest.HTTP_HEADERS)) { + Hashtable<String, String> http_hdrs = req.getExtDataInHashtable(name); + Enumeration<String> elms = http_hdrs.keys(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_HEADERS + LB + String.valueOf(counter++) + RB; + // hack + String n = elms.nextElement(); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n\r" + + prefix + parami + ".value=\"" + + CMSTemplate.escapeJavaScriptStringHTML( + http_hdrs.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all auth token stored in request. + else if (name.equalsIgnoreCase(IRequest.AUTH_TOKEN)) { + IAuthToken auth_token = req.getExtDataInAuthToken(name); + Enumeration<String> elms = auth_token.getElements(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.AUTH_TOKEN + LB + String.valueOf(counter++) + RB; + // hack + String n = (String) elms.nextElement(); + String v = + expandValue(prefix + parami + ".value", + auth_token.getInString(n)); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(n) + "\";\n" + v; + + arg.set(parami, new RawJS(rawJS)); + } + } // all others are request attrs from policy or internal modules. + else { + Object val; + if (req.isSimpleExtDataValue(name)) { + val = req.getExtDataInString(name); + } else { + val = req.getExtDataInStringArray(name); + if (val == null) { + val = req.getExtDataInHashtable(name); + } + } + String valstr = ""; + // hack + String parami = + IRequest.SERVER_ATTRS + LB + String.valueOf(saCounter++) + RB; + + valstr = expandValue(prefix + parami + ".value", val); + String rawJS = "new Object;\n\r" + + prefix + parami + ".name=\"" + + CMSTemplate.escapeJavaScriptString(name) + "\";\n" + + valstr; // java string already escaped in expandValue. + + arg.set(parami, new RawJS(rawJS)); + } + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_PHONE) + || name.equalsIgnoreCase(IRequest.REQUESTOR_EMAIL) + || name.equalsIgnoreCase(IRequest.REQUESTOR_COMMENTS) + || name.equalsIgnoreCase(IRequest.RESULT) + || name.equalsIgnoreCase(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE)) { + arg.addStringValue(name, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.REQUESTOR_NAME)) { + String requestorName = req.getExtDataInString(name); + + requestorName = requestorName.trim(); + if (requestorName.length() > 0) { + arg.addStringValue(name, requestorName); + } + } + + if (name.equalsIgnoreCase(IRequest.ERRORS)) { + Vector<String> errorsVector = req.getExtDataInStringVector(name); + if (errorsVector != null) { + StringBuffer errInfo = new StringBuffer(); + + for (int i = 0; i < errorsVector.size(); i++) { + errInfo.append(errorsVector.elementAt(i)); + errInfo.append("\n"); + } + arg.addStringValue(IRequest.ERRORS, errInfo.toString()); + } + } + if (name.equalsIgnoreCase(IRequest.ERROR)) { + arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name)); + } + + if (name.equalsIgnoreCase(IRequest.CERT_INFO)) { + // Get the certificate info from the request + RevokedCertImpl revokedCert[] = req.getExtDataInRevokedCertArray(IRequest.CERT_INFO); + + if (mDetails && revokedCert != null) { + if (argSet != null) { + for (int i = 0; i < revokedCert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + revokedCert[i].getSerialNumber(), 16); + + CRLExtensions crlExtensions = revokedCert[i].getExtensions(); + + if (crlExtensions != null) { + for (int k = 0; k < crlExtensions.size(); k++) { + Extension ext = (Extension) crlExtensions.elementAt(k); + + if (ext instanceof CRLReasonExtension) { + rarg.addStringValue("reason", + ((CRLReasonExtension) ext).getReason().toString()); + } + } + } else { + rarg.addStringValue("reason", + RevocationReason.UNSPECIFIED.toString()); + } + + argSet.addRepeatRecord(rarg); + } + } else { + arg.addBigIntegerValue("serialNumber", + revokedCert[0].getSerialNumber(), 16); + } + } + } + + if (name.equalsIgnoreCase(IRequest.OLD_SERIALS) && mDetails) { + BigInteger oldSerialNo[] = req.getExtDataInBigIntegerArray(IRequest.OLD_SERIALS); + + if (oldSerialNo != null) { + if (argSet != null) { + for (int i = 0; i < oldSerialNo.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + oldSerialNo[i], 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.OLD_CERTS) && mDetails) { + //X509CertImpl oldCert[] = + // (X509CertImpl[])req.get(IRequest.OLD_CERTS); + Certificate oldCert[] = + (Certificate[]) req.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (oldCert != null && oldCert.length > 0) { + if (oldCert[0] instanceof X509CertImpl) { + X509CertImpl xcert = (X509CertImpl) oldCert[0]; + + arg.addBigIntegerValue("serialNumber", xcert.getSerialNumber(), 16); + arg.addStringValue("subject", xcert.getSubjectDN().toString()); + if (req.getRequestType().equals(IRequest.GETCERTS_REQUEST)) { + for (int i = 0; i < oldCert.length; i++) { + IArgBlock rarg = CMS.createArgBlock(); + + xcert = (X509CertImpl) oldCert[i]; + rarg.addBigIntegerValue("serialNumber", + xcert.getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + } + } + } + } + + if (name.equalsIgnoreCase(IRequest.REVOKED_CERTS) && mDetails && + req.getRequestType().equals("getRevocationInfo")) { + RevokedCertImpl revokedCert[] = + req.getExtDataInRevokedCertArray(IRequest.REVOKED_CERTS); + + if (revokedCert != null && revokedCert[0] != null) { + boolean reasonFound = false; + CRLExtensions crlExtensions = revokedCert[0].getExtensions(); + + for (int k = 0; k < crlExtensions.size(); k++) { + Extension ext = (Extension) crlExtensions.elementAt(k); + + if (ext instanceof CRLReasonExtension) { + arg.addStringValue("reason", + ((CRLReasonExtension) ext).getReason().toString()); + reasonFound = true; + } + } + if (reasonFound == false) { + arg.addStringValue("reason", "unknown"); + } + } + } + } + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java b/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java new file mode 100644 index 000000000..b65c90fca --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java @@ -0,0 +1,621 @@ +// --- 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.request; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.X509Certificate; +import java.util.Locale; +import java.util.StringTokenizer; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.pkcs.PKCS7; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.pkix.cmc.CMCStatusInfo; +import org.mozilla.jss.pkix.cmc.PKIData; +import org.mozilla.jss.pkix.cmc.ResponseBody; +import org.mozilla.jss.pkix.cmc.TaggedAttribute; +import org.mozilla.jss.pkix.cms.EncapsulatedContentInfo; +import org.mozilla.jss.pkix.cms.IssuerAndSerialNumber; +import org.mozilla.jss.pkix.cms.SignedData; +import org.mozilla.jss.pkix.cms.SignerIdentifier; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.pkix.primitive.Name; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Check the status of a certificate request + * + * @version $Revision$, $Date$ + */ +public class CheckRequest extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 2791195859767119636L; + // constants + public static String FULL_RESPONSE = "cmcFullEnrollmentResponse"; + private final static String INFO = "CheckRequest"; + private final static String REQ_ID = "requestId"; + private final static String REQ_TYPE = "requestType"; + private final static String STATUS = "status"; + private final static String CREATE_ON = "createdOn"; + private final static String UPDATE_ON = "updatedOn"; + private final static String UPDATE_BY = "updatedBy"; + + private final static String TPL_FILE = "requestStatus.template"; + + // variables + private IRequestQueue mQueue = null; + private String mFormPath = null; + private String mAuthorityId = null; + + public CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Constructs request query servlet. + */ + public CheckRequest() + throws EBaseException { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "requestStatus.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); + mQueue = mAuthority.getRequestQueue(); + mAuthorityId = mAuthority.getId(); + mFormPath = "/" + mAuthorityId + "/" + TPL_FILE; + + mTemplates.remove(CMSRequest.SUCCESS); + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param requestId ID of the request to check + * <li>http.param format if 'id', then check the request based on the request ID parameter. If set to CMC, then use + * the 'queryPending' parameter. + * <li>http.param queryPending query formatted as a CMC request + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("checkRequest: in process!"); + SET transIds = null, sNonces = null; + boolean isCMCReq = false; + INTEGER bodyPartId = null; + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + // Note error is covered in the same template as success. + EBaseException error = null; + + String requestId = req.getParameter("requestId"); + String format = req.getParameter("format"); + + CMS.debug("checkRequest: requestId " + requestId); + + // They may check the status using CMC queryPending + String queryPending = req.getParameter("queryPending"); + + if (format != null && format.equals("cmc") && queryPending != null && !queryPending.equals("")) { + try { + isCMCReq = true; + byte[] cmcBlob = CMS.AtoB(queryPending); + ByteArrayInputStream cmcBlobIn = + new ByteArrayInputStream(cmcBlob); + + org.mozilla.jss.pkix.cms.ContentInfo cii = (org.mozilla.jss.pkix.cms.ContentInfo) + org.mozilla.jss.pkix.cms.ContentInfo.getTemplate().decode(cmcBlobIn); + SignedData cmcFullReq = (SignedData) + cii.getInterpretedContent(); + + EncapsulatedContentInfo ci = cmcFullReq.getContentInfo(); + + OBJECT_IDENTIFIER id = ci.getContentType(); + + if (!id.equals(OBJECT_IDENTIFIER.id_cct_PKIData) || !ci.hasContent()) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_PKIDATA")); + } + OCTET_STRING content = ci.getContent(); + ByteArrayInputStream s = new ByteArrayInputStream(content.toByteArray()); + PKIData pkiData = (PKIData) (new PKIData.Template()).decode(s); + + SEQUENCE controlSequence = pkiData.getControlSequence(); + int numControls = controlSequence.size(); + + for (int i = 0; i < numControls; i++) { + // decode message. + TaggedAttribute taggedAttr = (TaggedAttribute) controlSequence.elementAt(i); + OBJECT_IDENTIFIER type = taggedAttr.getType(); + + if (type.equals(OBJECT_IDENTIFIER.id_cmc_QueryPending)) { + bodyPartId = taggedAttr.getBodyPartID(); + SET requestIds = taggedAttr.getValues(); + int numReq = requestIds.size(); + + // We only process one for now. + if (numReq > 0) { + OCTET_STRING reqId = (OCTET_STRING) + ASN1Util.decode(OCTET_STRING.getTemplate(), + ASN1Util.encode(requestIds.elementAt(0))); + + requestId = new String(reqId.toByteArray()); + } + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_transactionId)) { + transIds = taggedAttr.getValues(); + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_recipientNonce)) { + // recipient nonce + } else if (type.equals(OBJECT_IDENTIFIER.id_cmc_senderNonce)) { + sNonces = taggedAttr.getValues(); + } + } + } catch (Exception e) { + error = new EBaseException(e.toString()); + } + } + + IArgBlock httpParams = cmsReq.getHttpParams(); + boolean importCert = httpParams.getValueAsBoolean("importCert", + false); + // xxx need to check why this is not available at startup + X509Certificate mCACerts[] = null; + + try { + mCACerts = ((ICertAuthority) mAuthority).getCACertChain().getChain(); + } catch (Exception e) { + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_CA_CHAIN_NOT_AVAILABLE")); + } + + if (requestId == null || requestId.trim().equals("")) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_NO_REQUEST_ID_PROVIDED")); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_NO_REQUEST_ID_PROVIDED")); + } + try { + new BigInteger(requestId); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", requestId)); + throw new EBaseException( + CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId)); + } + + IRequest r = mQueue.findRequest(new RequestId(requestId)); + + if (r == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_REQUEST_ID_NOT_FOUND_1", requestId)); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_REQUEST_ID_NOT_FOUND", requestId)); + } + + if (authToken != null) { + // if RA, requestOwner must match the group + String group = authToken.getInString("group"); + if ((group != null) && (group != "")) { + if (group.equals("Registration Manager Agents")) { + boolean groupMatched = false; + String requestOwner = r.getExtDataInString("requestOwner"); + if (requestOwner != null) { + if (requestOwner.equals(group)) + groupMatched = true; + } + if (groupMatched == false) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT_1", requestId.toString())); + throw new EBaseException( + CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT_1", requestId)); + } + } + } + } + + RequestStatus status = r.getRequestStatus(); + String note = r.getExtDataInString("requestNotes"); + + header.addStringValue("authority", mAuthorityId); + header.addLongValue(REQ_ID, Long.parseLong(r.getRequestId().toString())); + header.addStringValue(STATUS, status.toString()); + header.addLongValue(CREATE_ON, r.getCreationTime().getTime() / 1000); + header.addLongValue(UPDATE_ON, r.getModificationTime().getTime() / 1000); + if (note != null && note.length() > 0) + header.addStringValue("requestNotes", note); + + String type = r.getRequestType(); + Integer result = r.getExtDataInInteger(IRequest.RESULT); + + /* if (type.equals(IRequest.ENROLLMENT_REQUEST) && (r.get("profile") != null) && status.equals(RequestStatus.COMPLETE)) { + X509CertImpl cert = (X509CertImpl) r.get(IEnrollProfile.REQUEST_ISSUED_CERT); + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + cert.getSerialNumber(), 16); + argSet.addRepeatRecord(rarg); + } + */ + String profileId = r.getExtDataInString("profileId"); + if (profileId != null) { + result = IRequest.RES_SUCCESS; + } + if ((type != null) && (type.equals(IRequest.ENROLLMENT_REQUEST) || + type.equals(IRequest.RENEWAL_REQUEST)) && (status != null) && + status.equals(RequestStatus.COMPLETE) && (result != null) && + result.equals(IRequest.RES_SUCCESS)) { + Object o = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (profileId != null) { + X509CertImpl impl[] = new X509CertImpl[1]; + impl[0] = r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); + o = impl; + } + if (o != null && (o instanceof X509CertImpl[])) { + X509CertImpl[] certs = (X509CertImpl[]) o; + + if (certs != null && certs.length > 0) { + for (int i = 0; i < certs.length; i++) { + if (certs[i] != null) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addBigIntegerValue("serialNumber", + certs[i].getSerialNumber(), 16); + // add pkcs7 cert for importing + if (importCert || isCMCReq) { + //byte[] ba = certs[i].getEncoded(); + X509CertImpl[] certsInChain = new X509CertImpl[1]; + ; + if (mCACerts != null) { + for (int ii = 0; ii < mCACerts.length; ii++) { + if (certs[i].equals(mCACerts[ii])) { + certsInChain = new + X509CertImpl[mCACerts.length]; + break; + } + certsInChain = new X509CertImpl[mCACerts.length + 1]; + } + } + + // Set the EE cert + certsInChain[0] = certs[i]; + + // Set the Ca certificate chain + if (mCACerts != null) { + for (int ii = 0; ii < mCACerts.length; ii++) { + if (!certs[i].equals(mCACerts[ii])) + certsInChain[ii + 1] = (X509CertImpl) mCACerts[ii]; + } + } + // Wrap the chain into a degenerate P7 object + String p7Str; + + try { + PKCS7 p7 = new PKCS7(new AlgorithmId[0], + new netscape.security.pkcs.ContentInfo(new byte[0]), + certsInChain, + new netscape.security.pkcs.SignerInfo[0]); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + p7.encodeSignedData(bos); + byte[] p7Bytes = bos.toByteArray(); + + p7Str = CMS.BtoA(p7Bytes); + + StringTokenizer tokenizer = null; + + if (File.separator.equals("\\")) { + char[] nl = new char[2]; + + nl[0] = 10; + nl[1] = 13; + String nlstr = new String(nl); + + tokenizer = new StringTokenizer(p7Str, nlstr); + } else + tokenizer = new StringTokenizer(p7Str, "\n"); + StringBuffer res = new StringBuffer(); + + while (tokenizer.hasMoreTokens()) { + String elem = (String) tokenizer.nextToken(); + + res.append(elem); + } + + header.addStringValue("pkcs7ChainBase64", res.toString()); + + // compose full response + if (isCMCReq) { + SEQUENCE controlSeq = new SEQUENCE(); + int bpid = 1; + SEQUENCE bpids = new SEQUENCE(); + + if (bodyPartId != null) + bpids.addElement(bodyPartId); + CMCStatusInfo cmcStatusInfo = new + CMCStatusInfo(CMCStatusInfo.SUCCESS, bpids); + TaggedAttribute ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_cMCStatusInfo, + cmcStatusInfo); + + controlSeq.addElement(ta); + + // copy transactionID, senderNonce, + // create recipientNonce + if (transIds != null) { + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_transactionId, + transIds); + controlSeq.addElement(ta); + } + + if (sNonces != null) { + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_recipientNonce, + sNonces); + controlSeq.addElement(ta); + } + + String salt = CMSServlet.generateSalt(); + byte[] dig; + + try { + MessageDigest SHA1Digest = MessageDigest.getInstance("SHA1"); + + dig = SHA1Digest.digest(salt.getBytes()); + } catch (NoSuchAlgorithmException ex) { + dig = salt.getBytes(); + } + String b64E = CMS.BtoA(dig); + String[] newNonce = { b64E }; + + ta = new TaggedAttribute(new + INTEGER(bpid++), + OBJECT_IDENTIFIER.id_cmc_senderNonce, + new OCTET_STRING(newNonce[0].getBytes())); + controlSeq.addElement(ta); + + ResponseBody rb = new ResponseBody(controlSeq, new + SEQUENCE(), new + SEQUENCE()); + EncapsulatedContentInfo ci = new + EncapsulatedContentInfo(OBJECT_IDENTIFIER.id_cct_PKIResponse, + rb); + + org.mozilla.jss.crypto.X509Certificate x509cert = null; + + if (mAuthority instanceof ICertificateAuthority) { + x509cert = ((ICertificateAuthority) mAuthority).getCaX509Cert(); + } else if (mAuthority instanceof IRegistrationAuthority) { + x509cert = ((IRegistrationAuthority) mAuthority).getRACert(); + } + if (x509cert == null) + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_CMC_ERROR", + "No signing cert found.")); + + X509CertImpl cert = new X509CertImpl(x509cert.getEncoded()); + ByteArrayInputStream issuer1 = new + ByteArrayInputStream(((X500Name) cert.getIssuerDN()).getEncoded()); + Name issuer = (Name) Name.getTemplate().decode(issuer1); + IssuerAndSerialNumber ias = + new + IssuerAndSerialNumber(issuer, new INTEGER(cert.getSerialNumber() + .toString())); + SignerIdentifier si = new + SignerIdentifier(SignerIdentifier.ISSUER_AND_SERIALNUMBER, ias, null); + + // SHA1 is the default digest Alg for now. + DigestAlgorithm digestAlg = null; + SignatureAlgorithm signAlg = null; + org.mozilla.jss.crypto.PrivateKey privKey = + CryptoManager.getInstance().findPrivKeyByCert(x509cert); + org.mozilla.jss.crypto.PrivateKey.Type keyType = privKey.getType(); + + if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.RSA)) + signAlg = SignatureAlgorithm.RSASignatureWithSHA1Digest; + else if (keyType.equals(org.mozilla.jss.crypto.PrivateKey.DSA)) + signAlg = SignatureAlgorithm.DSASignatureWithSHA1Digest; + MessageDigest SHADigest = null; + byte[] digest = null; + + try { + SHADigest = MessageDigest.getInstance("SHA1"); + digestAlg = DigestAlgorithm.SHA1; + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + rb.encode((OutputStream) ostream); + digest = SHADigest.digest(ostream.toByteArray()); + } catch (NoSuchAlgorithmException ex) { + //log("digest fail"); + } + + org.mozilla.jss.pkix.cms.SignerInfo signInfo = new + org.mozilla.jss.pkix.cms.SignerInfo(si, null, null, + OBJECT_IDENTIFIER.id_cct_PKIResponse, + digest, signAlg, + privKey); + SET signInfos = new SET(); + + signInfos.addElement(signInfo); + + SET digestAlgs = new SET(); + + if (digestAlg != null) { + AlgorithmIdentifier ai = new + AlgorithmIdentifier(digestAlg.toOID(), + null); + + digestAlgs.addElement(ai); + } + + SET jsscerts = new SET(); + + for (int j = 0; j < certsInChain.length; j++) { + ByteArrayInputStream is = new + ByteArrayInputStream(certsInChain[j].getEncoded()); + org.mozilla.jss.pkix.cert.Certificate certJss = + (org.mozilla.jss.pkix.cert.Certificate) + org.mozilla.jss.pkix.cert.Certificate.getTemplate().decode(is); + + jsscerts.addElement(certJss); + } + + SignedData fResponse = new + SignedData(digestAlgs, ci, + jsscerts, null, signInfos); + org.mozilla.jss.pkix.cms.ContentInfo fullResponse = + new + org.mozilla.jss.pkix.cms.ContentInfo( + org.mozilla.jss.pkix.cms.ContentInfo.SIGNED_DATA, fResponse); + ByteArrayOutputStream ostream = new + ByteArrayOutputStream(); + + fullResponse.encode((OutputStream) ostream); + byte[] fr = ostream.toByteArray(); + + header.addStringValue(FULL_RESPONSE, CMS.BtoA(fr)); + } + } catch (Exception e) { + e.printStackTrace(); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_FORMING_PKCS7_1", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_FORMING_PKCS7_ERROR")); + } + } + argSet.addRepeatRecord(rarg); + } + } + } + } + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/IReqParser.java b/base/common/src/com/netscape/cms/servlet/request/IReqParser.java new file mode 100644 index 000000000..f90e97b70 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/IReqParser.java @@ -0,0 +1,42 @@ +// --- 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.request; + +import java.util.Locale; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; + +/** + * An interface representing a request parser which + * converts Java request object into name value + * pairs and vice versa. + * <P> + * + * @version $Revision$, $Date$ + */ +public interface IReqParser { + + /** + * Maps request object into argument block. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException; +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java b/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java new file mode 100644 index 000000000..b7ddc16d4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java @@ -0,0 +1,81 @@ +// --- 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.request; + +import java.math.BigInteger; +import java.util.Locale; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.key.KeyRecordParser; + +/** + * Output a 'pretty print' of a Key Archival request + * + * @version $Revision$, $Date$ + */ +public class KeyReqParser extends ReqParser { + + public static final KeyReqParser PARSER = new KeyReqParser(); + public static final String OUTPUT_SERIALNO = "serialNumber"; + + /** + * Constructs a certificate request parser. + */ + public KeyReqParser() { + } + + /** + * Fills in certificate specific request attributes. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + // fill in the standard attributes + super.fillRequestIntoArg(l, req, argSet, arg); + + String type = req.getRequestType(); + + if (type.equals(IRequest.ENROLLMENT_REQUEST)) { + BigInteger recSerialNo = req.getExtDataInBigInteger("keyRecord"); + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) CMS.getSubsystem("kra"); + if (kra != null) { + KeyRecordParser.fillRecordIntoArg( + kra.getKeyRepository().readKeyRecord(recSerialNo), + arg); + } else { + throw new EBaseException("KRA is not available"); + } + + } else if (type.equals(IRequest.KEYRECOVERY_REQUEST)) { + BigInteger kid = req.getExtDataInBigInteger("serialNumber"); + + arg.addStringValue(OUTPUT_SERIALNO, kid.toString()); + + // for async recovery + String agents = (String) req.getExtDataInString("approvingAgents"); + arg.addStringValue("approvingAgents", agents); + } else { + System.out.println("Bad Request " + type); + // invalid request + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java new file mode 100644 index 000000000..cd08f46bb --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResource.java @@ -0,0 +1,69 @@ +package com.netscape.cms.servlet.request; + +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; + +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.request.model.ArchivalRequestData; +import com.netscape.cms.servlet.request.model.KeyRequestInfo; +import com.netscape.cms.servlet.request.model.RecoveryRequestData; + +@Path("/keyrequest") +public interface KeyRequestResource { + public final String SYMMETRIC_KEY_TYPE = "symmetricKey"; + public final String PASS_PHRASE_TYPE = "passPhrase"; + public final String ASYMMETRIC_KEY_TYPE = "asymmetricKey"; + + /** + * Used to retrieve key request info for a specific request + */ + @GET + @Path("{id}") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + public KeyRequestInfo getRequestInfo(@PathParam("id") RequestId id); + + // Archiving - used to test integration with a browser + @POST + @Path("archive") + @Produces({ MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED}) + public KeyRequestInfo archiveKey(MultivaluedMap<String, String> form); + + @POST + @Path("archive") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyRequestInfo archiveKey(ArchivalRequestData data); + + //Recovery - used to test integration with a browser + @POST + @Path("recover") + @Produces({ MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_FORM_URLENCODED}) + public KeyRequestInfo recoverKey(MultivaluedMap<String, String> form); + + @POST + @Path("recover") + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON }) + public KeyRequestInfo recoverKey(RecoveryRequestData data); + + @POST + @Path("approve/{id}") + public void approveRequest(@PathParam("id") RequestId id); + + @POST + @Path("reject/{id}") + public void rejectRequest(@PathParam("id") RequestId id); + + @POST + @Path("cancel/{id}") + public void cancelRequest(@PathParam("id") RequestId id); + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java new file mode 100644 index 000000000..43e58bbdc --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestResourceService.java @@ -0,0 +1,165 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.request; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.request.model.ArchivalRequestData; +import com.netscape.cms.servlet.request.model.KeyRequestDAO; +import com.netscape.cms.servlet.request.model.KeyRequestInfo; +import com.netscape.cms.servlet.request.model.RecoveryRequestData; + +/** + * @author alee + * + */ +public class KeyRequestResourceService extends CMSResourceService implements KeyRequestResource { + + @Context + UriInfo uriInfo; + + /** + * Used to retrieve key request info for a specific request + */ + public KeyRequestInfo getRequestInfo(RequestId id) { + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + KeyRequestInfo info; + try { + info = dao.getRequest(id, uriInfo); + } catch (EBaseException e) { + // log error + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + if (info == null) { + // request does not exist + throw new WebApplicationException(Response.Status.NOT_FOUND); + } + return info; + } + + // Archiving - used to test integration with a browser + public KeyRequestInfo archiveKey(MultivaluedMap<String, String> form) { + ArchivalRequestData data = new ArchivalRequestData(form); + return archiveKey(data); + } + + public KeyRequestInfo archiveKey(ArchivalRequestData data) { + // auth and authz + // Catch this before internal server processing has to deal with it + + if (data == null || data.getClientId() == null + || data.getWrappedPrivateData() == null + || data.getDataType() == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + + KeyRequestDAO dao = new KeyRequestDAO(); + KeyRequestInfo info; + try { + info = dao.submitRequest(data, uriInfo); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return info; + } + + //Recovery - used to test integration with a browser + public KeyRequestInfo recoverKey(MultivaluedMap<String, String> form) { + RecoveryRequestData data = new RecoveryRequestData(form); + return recoverKey(data); + } + + public KeyRequestInfo recoverKey(RecoveryRequestData data) { + // auth and authz + + //Check for entirely illegal data combination here + //Catch this before the internal server processing has to deal with it + //If data has been provided, we need at least the wrapped session key, + //or the command is invalid. + if (data == null || (data.getTransWrappedSessionKey() == null + && data.getSessionWrappedPassphrase() != null)) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + KeyRequestDAO dao = new KeyRequestDAO(); + KeyRequestInfo info; + try { + info = dao.submitRequest(data, uriInfo); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return info; + } + + public void approveRequest(RequestId id) { + if (id == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + try { + dao.approveRequest(id); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + public void rejectRequest(RequestId id) { + if (id == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + try { + dao.rejectRequest(id); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } + + public void cancelRequest(RequestId id) { + if (id == null) { + throw new WebApplicationException(Response.Status.BAD_REQUEST); + } + // auth and authz + KeyRequestDAO dao = new KeyRequestDAO(); + try { + dao.cancelRequest(id); + } catch (EBaseException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResource.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResource.java new file mode 100644 index 000000000..fd6bc4c27 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResource.java @@ -0,0 +1,34 @@ +package com.netscape.cms.servlet.request; + +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.request.model.KeyRequestInfos; + +@Path("/keyrequests") +public interface KeyRequestsResource { + + public static final int DEFAULT_START = 0; + public static final int DEFAULT_PAGESIZE = 20; + public static final int DEFAULT_MAXRESULTS = 100; + public static final int DEFAULT_MAXTIME = 10; + + /** + * Used to generate list of key requests based on the search parameters + */ + @GET + @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) + public KeyRequestInfos listRequests(@QueryParam("requestState") String requestState, + @QueryParam("requestType") String requestType, + @QueryParam("clientID") String clientID, + @DefaultValue(""+DEFAULT_START) @QueryParam("start") RequestId start, + @DefaultValue(""+DEFAULT_PAGESIZE) @QueryParam("pageSize") int pageSize, + @DefaultValue(""+DEFAULT_MAXRESULTS) @QueryParam("maxResults") int maxResults, + @DefaultValue(""+DEFAULT_MAXTIME) @QueryParam("maxTime") int maxTime); + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResourceService.java b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResourceService.java new file mode 100644 index 000000000..11898ef7a --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/KeyRequestsResourceService.java @@ -0,0 +1,101 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.request; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSResourceService; +import com.netscape.cms.servlet.request.model.KeyRequestDAO; +import com.netscape.cms.servlet.request.model.KeyRequestInfos; +import com.netscape.cmsutil.ldap.LDAPUtil; + +/** + * @author alee + * + */ +public class KeyRequestsResourceService extends CMSResourceService implements KeyRequestsResource{ + + @Context + UriInfo uriInfo; + + /** + * Used to generate list of key requests based on the search parameters + */ + public KeyRequestInfos listRequests(String requestState, String requestType, String clientID, + RequestId start, int pageSize, int maxResults, int maxTime) { + // auth and authz + + // get ldap filter + String filter = createSearchFilter(requestState, requestType, clientID); + CMS.debug("listRequests: filter is " + filter); + + // get start marker + if (start == null) { + start = new RequestId(KeyRequestsResource.DEFAULT_START); + } + + KeyRequestDAO reqDAO = new KeyRequestDAO(); + KeyRequestInfos requests; + try { + requests = reqDAO.listRequests(filter, start, pageSize, maxResults, maxTime, uriInfo); + } catch (EBaseException e) { + CMS.debug("listRequests: error in obtaining request results" + e); + e.printStackTrace(); + throw new WebApplicationException(Response.Status.INTERNAL_SERVER_ERROR); + } + return requests; + } + + private String createSearchFilter(String requestState, String requestType, String clientID) { + String filter = ""; + int matches = 0; + + if ((requestState == null) && (requestType == null) && (clientID == null)) { + filter = "(requeststate=*)"; + return filter; + } + + if (requestState != null) { + filter += "(requeststate=" + LDAPUtil.escape(requestState) + ")"; + matches ++; + } + + if (requestType != null) { + filter += "(requesttype=" + LDAPUtil.escape(requestType) + ")"; + matches ++; + } + + if (clientID != null) { + filter += "(clientID=" + LDAPUtil.escape(clientID) + ")"; + matches ++; + } + + if (matches > 1) { + filter = "(&" + filter + ")"; + } + + return filter; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java b/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java new file mode 100644 index 000000000..820e9a654 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java @@ -0,0 +1,1933 @@ +// --- 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.request; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.util.Date; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.extensions.NSCertTypeExtension; +import netscape.security.extensions.PresenceServerExtension; +import netscape.security.util.DerValue; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.BasicConstraintsExtension; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.CertificateVersion; +import netscape.security.x509.Extension; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.AuthToken; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.logging.AuditFormat; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.publish.IPublisherProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.usrgrp.IGroup; +import com.netscape.certsrv.usrgrp.IUGSubsystem; +import com.netscape.certsrv.usrgrp.IUser; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.cert.ImportCertsTemplateFiller; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; +import com.netscape.cms.servlet.common.ICMSTemplateFiller; +import com.netscape.cmsutil.util.Utils; + +/** + * Agent operations on Certificate requests. This servlet is used + * by an Agent to approve, reject, reassign, or change a certificate + * request. + * + * @version $Revision$, $Date$ + */ +public class ProcessCertReq extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 812464895240811318L; + private final static String INFO = "processReq"; + private final static String SEQNUM = "seqNum"; + private final static String TO_DO = "toDo"; + private final static String TPL_FILE = "processCertReq.template"; + + private IRequestQueue mQueue = null; + private String mFormPath = null; + private IReqParser mParser = null; + private IPublisherProcessor mPublisherProcessor = null; + private boolean mExtraAgentParams = false; + + // for RA only since it does not have a database. + private final static String REQ_COMPLETED_TEMPLATE = "ra/RequestCompleted.template"; + private final static String PROP_REQ_COMPLETED_TEMPLATE = "requestCompletedTemplate"; + private final static String PROP_EXTRA_AGENT_PARAMS = "extraAgentParams"; + private static ICMSTemplateFiller REQ_COMPLETED_FILLER = new RAReqCompletedFiller(); + private String mReqCompletedTemplate = null; + private final static String CERT_TYPE = "certType"; + + private String auditServiceID = ILogger.UNIDENTIFIED; + private final static String AGENT_CA_CLONE_ENROLLMENT_SERVLET = + "caProcessCertReq"; + private final static String AGENT_RA_CLONE_ENROLLMENT_SERVLET = + "raProcessCertReq"; + private final static String SIGNED_AUDIT_ACCEPTANCE = "accept"; + private final static String SIGNED_AUDIT_CANCELLATION = "cancel"; + private final static String SIGNED_AUDIT_CLONING = "clone"; + private final static String SIGNED_AUDIT_REJECTION = "reject"; + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + private final static String[] SIGNED_AUDIT_MANUAL_CANCELLATION_REASON = new String[] { + + /* 0 */"manual non-profile cert request cancellation: " + + "request cannot be processed due to an " + + "authorization failure", + + /* 1 */"manual non-profile cert request cancellation: " + + "no reason has been given for cancelling this " + + "cert request", + + /* 2 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException", + + /* 3 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to an IOException", + + /* 4 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to a CertificateException", + + /* 5 */"manual non-profile cert request cancellation: " + + "indeterminate reason for inability to process " + + "cert request due to a NoSuchAlgorithmException" + }; + private final static String[] SIGNED_AUDIT_MANUAL_REJECTION_REASON = new String[] { + + /* 0 */"manual non-profile cert request rejection: " + + "request cannot be processed due to an " + + "authorization failure", + + /* 1 */"manual non-profile cert request rejection: " + + "no reason has been given for rejecting this " + + "cert request", + + /* 2 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException", + + /* 3 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an IOException", + + /* 4 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to a CertificateException", + + /* 5 */"manual non-profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to a NoSuchAlgorithmException" + }; + private final static String LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST = + "LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + /** + * Process request. + */ + public ProcessCertReq() + throws EBaseException { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "processCertReq.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + try { + super.init(sc); + + // determine the service ID for signed audit log messages + String id = sc.getInitParameter(CMSServlet.PROP_ID); + + if (id != null) { + if (!(auditServiceID.equals( + AGENT_CA_CLONE_ENROLLMENT_SERVLET)) + && !(auditServiceID.equals( + AGENT_RA_CLONE_ENROLLMENT_SERVLET))) { + auditServiceID = ILogger.UNIDENTIFIED; + } else { + auditServiceID = id.trim(); + } + } + + mQueue = mAuthority.getRequestQueue(); + mPublisherProcessor = + ((ICertAuthority) mAuthority).getPublisherProcessor(); + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + mParser = CertReqParser.DETAIL_PARSER; + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + + try { + mReqCompletedTemplate = sc.getInitParameter( + PROP_REQ_COMPLETED_TEMPLATE); + if (mReqCompletedTemplate == null) + mReqCompletedTemplate = REQ_COMPLETED_TEMPLATE; + String tmp = sc.getInitParameter(PROP_EXTRA_AGENT_PARAMS); + + if (tmp != null && tmp.trim().equalsIgnoreCase("true")) + mExtraAgentParams = true; + else + mExtraAgentParams = false; + } catch (Exception e) { + // does not happen. + } + } catch (ServletException eAudit1) { + // rethrow caught exception + throw eAudit1; + } + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param seqNum request id + * <li>http.param notValidBefore certificate validity - notBefore - in seconds since jan 1, 1970 + * <li>http.param notValidAfter certificate validity - notAfter - in seconds since jan 1, 1970 + * <li>http.param subject certificate subject name + * <li>http.param toDo requested action (can be one of: clone, reject, accept, cancel) + * <li>http.param signatureAlgorithm certificate signing algorithm + * <li>http.param addExts base-64, DER encoded Extension or SEQUENCE OF Extensions to add to certificate + * <li>http.param pathLenConstraint integer path length constraint to use in BasicConstraint extension if applicable + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + long startTime = CMS.getCurrentDate().getTime(); + String toDo = null; + String subject = null; + String signatureAlgorithm = null; + long notValidBefore = 0; + long notValidAfter = 0; + BigInteger seqNum = BigInteger.ONE.negate(); + EBaseException error = null; + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + if (req.getParameter(SEQNUM) != null) { + CMS.debug( + "ProcessCertReq: parameter seqNum " + req.getParameter(SEQNUM)); + seqNum = new BigInteger(req.getParameter(SEQNUM)); + } + String notValidBeforeStr = req.getParameter("notValidBefore"); + + if (notValidBeforeStr != null && notValidBeforeStr.length() > 0) { + notValidBefore = Long.parseLong(notValidBeforeStr); + notValidBefore *= 1000; + } + String notValidAfterStr = req.getParameter("notValidAfter"); + + if (notValidAfterStr != null && notValidAfterStr.length() > 0) { + notValidAfter = Long.parseLong(notValidAfterStr); + notValidAfter *= 1000; + } + + toDo = req.getParameter("toDo"); + + subject = req.getParameter("subject"); + signatureAlgorithm = req.getParameter("signatureAlgorithm"); + + IRequest r = null; + + if (seqNum.compareTo(BigInteger.ONE.negate()) > 0) { + r = mQueue.findRequest(new RequestId(seqNum)); + } + + if (seqNum.compareTo(BigInteger.ONE.negate()) > 0 && r != null) { + processX509(cmsReq, argSet, header, seqNum, req, resp, + toDo, signatureAlgorithm, subject, + notValidBefore, notValidAfter, locale[0], startTime); + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_INVALID_REQUEST_ID_1", seqNum.toString())); + error = new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + seqNum.toString())); + } + } catch (EBaseException e) { + error = e; + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, "Error " + e); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + return; + } + + /** + * Process X509 certificate enrollment request and send request information + * to the caller. + * <P> + * + * (Certificate Request - an "agent" cert request for "cloning") + * <P> + * + * (Certificate Request Processed - either a manual "agent" non-profile based cert acceptance, a manual "agent" + * non-profile based cert cancellation, or a manual "agent" non-profile based cert rejection) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST used when a non-profile cert request is made + * (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a certificate request has just been + * through the approval process + * </ul> + * + * @param cmsReq a certificate enrollment request + * @param argSet CMS template parameters + * @param header argument block + * @param seqNum sequence number + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @param toDo string representing the requested action (can be one of: + * clone, reject, accept, cancel) + * @param signatureAlgorithm string containing the signature algorithm + * @param subject string containing the subject name of the certificate + * @param notValidBefore certificate validity - notBefore - in seconds + * since Jan 1, 1970 + * @param notValidAfter certificate validity - notAfter - in seconds since + * Jan 1, 1970 + * @param locale the system locale + * @param startTime the current date + * @exception EBaseException an error has occurred + */ + private void processX509(CMSRequest cmsReq, + CMSTemplateParams argSet, IArgBlock header, + BigInteger seqNum, HttpServletRequest req, + HttpServletResponse resp, + String toDo, String signatureAlgorithm, + String subject, + long notValidBefore, long notValidAfter, + Locale locale, long startTime) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = ILogger.UNIDENTIFIED; + String auditCertificateSubjectName = subject; + String auditInfoName = auditInfoName(toDo); + String id = null; + + // "normalize" the "auditCertificateSubjectName" + if (auditCertificateSubjectName != null) { + // NOTE: This is ok even if the cert subject name is "" (empty)! + auditCertificateSubjectName = auditCertificateSubjectName.trim(); + } else { + // NOTE: Here, the cert subject name is MISSING, not "" (empty)! + auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + try { + IRequest r = mQueue.findRequest(new RequestId(seqNum)); + + if (r != null) { + // overwrite "auditRequesterID" if and only if "id" != null + id = r.getRequestId().toString(); + if (id != null) { + auditRequesterID = id.trim(); + } + } + + if (mAuthority != null) + header.addStringValue("authorityid", mAuthority.getId()); + + if (toDo != null) { + // for audit log + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "execute"); + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + + // store a message in the signed audit log file + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[0]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[0]); + + audit(auditMessage); + } + + return; + } + + String authMgr = AuditFormat.NOAUTH; + + if (authToken != null) { + authMgr = + authToken.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } + String agentID = authToken.getInString("userid"); + String initiative = AuditFormat.FROMAGENT + " agentID: " + agentID; + + // Get the certificate info from the request + X509CertInfo certInfo[] = r.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + header.addStringValue("toDo", toDo); + if (toDo.equals("accept")) { + + if (certInfo != null) { + int alterationCounter = 0; + + for (int i = 0; i < certInfo.length; i++) { + CertificateAlgorithmId certAlgId = + (CertificateAlgorithmId) + certInfo[i].get(X509CertInfo.ALGORITHM_ID); + + AlgorithmId algId = (AlgorithmId) + certAlgId.get(CertificateAlgorithmId.ALGORITHM); + + if (!(algId.getName().equals(signatureAlgorithm))) { + alterationCounter++; + AlgorithmId newAlgId = AlgorithmId.getAlgorithmId(signatureAlgorithm); + + certInfo[i].set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId(newAlgId)); + } + + CertificateSubjectName certSubject = + (CertificateSubjectName) + certInfo[i].get(X509CertInfo.SUBJECT); + + if (subject != null && + !(certSubject.toString().equals(subject))) { + + alterationCounter++; + certInfo[i].set(X509CertInfo.SUBJECT, + new CertificateSubjectName( + (new X500Name(subject)))); + } + + CertificateValidity certValidity = + (CertificateValidity) + certInfo[i].get(X509CertInfo.VALIDITY); + Date currentTime = CMS.getCurrentDate(); + boolean validityChanged = false; + + // only override these values if agent specified them + if (notValidBefore > 0) { + Date notBefore = (Date) certValidity.get( + CertificateValidity.NOT_BEFORE); + + if (notBefore.getTime() == 0 || + notBefore.getTime() != notValidBefore) { + Date validFrom = new Date(notValidBefore); + + notBefore = (notValidBefore == 0) ? currentTime : validFrom; + certValidity.set(CertificateValidity.NOT_BEFORE, + notBefore); + validityChanged = true; + } + } + if (notValidAfter > 0) { + Date validTo = new Date(notValidAfter); + Date notAfter = (Date) + certValidity.get(CertificateValidity.NOT_AFTER); + + if (notAfter.getTime() == 0 || + notAfter.getTime() != notValidAfter) { + notAfter = currentTime; + notAfter = (notValidAfter == 0) ? currentTime : validTo; + certValidity.set(CertificateValidity.NOT_AFTER, + notAfter); + validityChanged = true; + } + } + if (validityChanged) { + // this set() trigger this rebuild of internal + // raw der encoding cache of X509CertInfo. + // Otherwise, the above change wont have effect. + certInfo[i].set(X509CertInfo.VALIDITY, certValidity); + } + + if (certInfo[i].get(X509CertInfo.VERSION) == null) { + certInfo[i].set(X509CertInfo.VERSION, + new CertificateVersion( + CertificateVersion.V3)); + } + + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) + certInfo[i].get(X509CertInfo.EXTENSIONS); + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_ERROR_PARSING_EXTENS", e.toString())); + } + + // 99/08/31 #361906 - handling additional extensions + String addExts = req.getParameter("addExts"); + + if (addExts != null && !addExts.trim().equals("")) { + Vector<Extension> extsToBeAdded = new Vector<Extension>(); + + byte[] b = Utils.base64decode(addExts); + + // this b can be "Extension" Or "SEQUENCE OF Extension" + try { + DerValue b_der = new DerValue(b); + + while (b_der.data.available() != 0) { + Extension de = new Extension(b_der.data.getDerValue()); + + extsToBeAdded.addElement(de); + } + } catch (IOException e) { + // it could be a single extension + Extension de = new Extension(new DerValue(b)); + + extsToBeAdded.addElement(de); + } + if (extsToBeAdded.size() > 0) { + if (extensions == null) { + extensions = new CertificateExtensions(); + certInfo[i].set(X509CertInfo.EXTENSIONS, extensions); + } + for (int j = 0; j < extsToBeAdded.size(); j++) { + Extension theExt = (Extension) extsToBeAdded.elementAt(j); + + extensions.set(theExt.getExtensionId().toString(), theExt); + } + } + } + + if (extensions != null) { + try { + NSCertTypeExtension nsExtensions = + (NSCertTypeExtension) + extensions.get( + NSCertTypeExtension.NAME); + + if (nsExtensions != null) { + updateNSExtension(req, nsExtensions); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_PROCESS_NETSCAPE_EXTENSION", e.toString())); + } + + String pathLength = req.getParameter("pathLenConstraint"); + + if (pathLength != null) { + try { + int pathLen = Integer.parseInt(pathLength); + BasicConstraintsExtension bcExt = + (BasicConstraintsExtension) + extensions.get( + BasicConstraintsExtension.NAME); + + if (bcExt != null) { + Integer bcPathLen = (Integer) bcExt.get(BasicConstraintsExtension.PATH_LEN); + Boolean isCA = (Boolean) bcExt.get(BasicConstraintsExtension.IS_CA); + + if (bcPathLen != null && + bcPathLen.intValue() != pathLen && + isCA != null) { + BasicConstraintsExtension bcExt0 = + new BasicConstraintsExtension(isCA.booleanValue(), pathLen); + + extensions.delete(BasicConstraintsExtension.NAME); + extensions.set(BasicConstraintsExtension.NAME, + (Extension) bcExt0); + alterationCounter++; + } + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_PROCESS_CONSTRAINTS_EXTENSION", + e.toString())); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_PROCESS_CONSTRAINTS_EXTENSION", + e.toString())); + } + } + + // handle Presence Server Extension + String PSE_Enable = req.getParameter("PSE_Enable"); + + if (PSE_Enable != null) { + boolean Critical = (req.getParameter("PSE_Critical") != null); + int Version = 0; + + try { + Version = Integer.parseInt(req.getParameter("PSE_Version")); + } catch (Exception e1) { + } + String StreetAddress = req.getParameter("PSE_StreetAddress"); + + if (StreetAddress == null) { + StreetAddress = ""; + } + String TelephoneNumber = req.getParameter("PSE_TelephoneNumber"); + + if (TelephoneNumber == null) { + TelephoneNumber = ""; + } + String RFC822Name = req.getParameter("PSE_RFC822Name"); + + if (RFC822Name == null) { + RFC822Name = ""; + } + String IMID = req.getParameter("PSE_IMID"); + + if (IMID == null) { + IMID = ""; + } + String HostName = req.getParameter("PSE_HostName"); + + if (HostName == null) { + HostName = ""; + } + int PortNumber = 0; + + try { + PortNumber = Integer.parseInt(req.getParameter("PSE_PortNumber")); + } catch (Exception e1) { + } + int MaxUsers = 0; + + try { + MaxUsers = Integer.parseInt(req.getParameter("PSE_MaxUsers")); + } catch (Exception e1) { + } + int ServiceLevel = 0; + + try { + ServiceLevel = Integer.parseInt(req.getParameter("PSE_ServiceLevel")); + } catch (Exception e1) { + } + // create extension + PresenceServerExtension pseExt = + new PresenceServerExtension(Critical, Version, StreetAddress, + TelephoneNumber, RFC822Name, IMID, HostName, PortNumber, MaxUsers, + ServiceLevel); + + extensions.set(pseExt.getExtensionId().toString(), pseExt); + } + + if (mExtraAgentParams) { + @SuppressWarnings("unchecked") + Enumeration<String> extraparams = req.getParameterNames(); + int l = IRequest.AGENT_PARAMS.length() + 1; + int ap_counter = 0; + Hashtable<String, String> agentparamsargblock = new Hashtable<String, String>(); + + if (extraparams != null) { + while (extraparams.hasMoreElements()) { + String s = extraparams.nextElement(); + + if (s.startsWith(IRequest.AGENT_PARAMS)) { + String param_value = req.getParameter(s); + + if (param_value != null) { + String new_name = s.substring(l); + + agentparamsargblock.put(new_name, param_value); + ap_counter += 1; + } + } + } + } + if (ap_counter > 0) { + r.setExtData(IRequest.AGENT_PARAMS, agentparamsargblock); + alterationCounter++; + } + } + + // this set() trigger this rebuild of internal + // raw der encoding cache of X509CertInfo. + // Otherwise, the above change wont have effect. + certInfo[i].set(X509CertInfo.EXTENSIONS, extensions); + } + alterationCounter += updateExtensionsInRequest(req, r); + } + if (alterationCounter > 0) { + mQueue.updateRequest(r); + } + } + + mQueue.approveRequest(r); + + if (r.getRequestStatus().equals(RequestStatus.PENDING)) { + cmsReq.setResult(r); + cmsReq.setStatus(CMSRequest.PENDING); + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "pending", + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "pending", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "pending" } + ); + } + } + } else if (r.getRequestStatus().equals( + RequestStatus.APPROVED) || + r.getRequestStatus().equals( + RequestStatus.SVC_PENDING)) { + cmsReq.setResult(r); + cmsReq.setStatus(CMSRequest.SVC_PENDING); + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + r.getRequestStatus(), + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + r.getRequestStatus(), + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + r.getRequestStatus() } + ); + } + } + } else if (r.getRequestStatus().equals( + RequestStatus.COMPLETE)) { + cmsReq.setStatus(CMSRequest.SUCCESS); + + // XXX make the repeat record. + // Get the certificate(s) from the request + X509CertImpl issuedCerts[] = + r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + // return potentially more than one certificates. + if (issuedCerts != null) { + long endTime = CMS.getCurrentDate().getTime(); + StringBuffer sbuf = new StringBuffer(); + + //header.addBigIntegerValue("serialNumber", + //issuedCerts[0].getSerialNumber(),16); + for (int i = 0; i < issuedCerts.length; i++) { + if (i != 0) + sbuf.append(", "); + sbuf.append("0x" + + issuedCerts[i].getSerialNumber().toString(16)); + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "completed", + issuedCerts[i].getSubjectDN(), + "cert issued serial number: 0x" + + + issuedCerts[i].getSerialNumber().toString(16) + " time: " + + (endTime - startTime) } + ); + + // store a message in the signed audit log file + // (one for each manual "agent" + // cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + auditInfoCertValue(issuedCerts[i])); + + audit(auditMessage); + } + header.addStringValue( + "serialNumber", sbuf.toString()); + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "completed", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "completed" } + ); + } + + // store a message in the signed audit log file + // (manual "agent" cert request processed + // - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } + + // grant trusted manager or agent privileges + try { + int res = grant_privileges( + cmsReq, r, issuedCerts, header); + + if (res != 0) { + header.addStringValue(GRANT_ERROR, "SUCCESS"); + } + } catch (EBaseException e) { + header.addStringValue(GRANT_ERROR, e.toString()); + } + + // if this is a RA, show the certificate right away + // since ther is no cert database. + /* + if (mAuthority instanceof RegistrationAuthority) { + Object[] results = + new Object[] { issuedCerts, grantError }; + cmsReq.setResult(results); + renderTemplate(cmsReq, + mReqCompletedTemplate, REQ_COMPLETED_FILLER); + + return; + } + */ + + cmsReq.setResult(r); + + String scheme = req.getScheme(); + + if (scheme.equals("http") && + connectionIsSSL(req)) + scheme = "https"; + + /* + header.addStringValue( + "authorityid", mAuthority.getId()); + header.addStringValue("serviceURL", scheme +"://"+ + req.getServerName() + ":"+ + req.getServerPort() + + req.getRequestURI()); + */ + + if (mPublisherProcessor != null && mPublisherProcessor.ldapEnabled()) { + header.addStringValue("dirEnabled", "yes"); + + Integer[] ldapPublishStatus = + r.getExtDataInIntegerArray("ldapPublishStatus"); + int certsUpdated = 0; + + if (ldapPublishStatus != null) { + for (int i = 0; i < ldapPublishStatus.length; i++) { + if (ldapPublishStatus[i] == IRequest.RES_SUCCESS) { + certsUpdated++; + } + } + } + header.addIntegerValue("certsUpdated", certsUpdated); + + } else { + header.addStringValue("dirEnabled", "no"); + } + } + + } else if (toDo.equals("reject")) { + mQueue.rejectRequest(r); + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "rejected", + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "rejected", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "rejected" } + ); + } + } + + // store a message in the signed audit log file + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[1]); + + audit(auditMessage); + + } else if (toDo.equals("cancel")) { + mQueue.cancelRequest(r); + + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "canceled", + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "canceled", + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "canceled" } + ); + } + + } + + // store a message in the signed audit log file + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[1]); + + audit(auditMessage); + + } else if (toDo.equals("clone")) { + IRequest clonedRequest = mQueue.cloneAndMarkPending(r); + + header.addStringValue("clonedRequestId", + clonedRequest.getRequestId().toString()); + + if (certInfo != null) { + for (int i = 0; i < certInfo.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "cloned to reqID: " + + clonedRequest.getRequestId().toString(), + certInfo[i].get(X509CertInfo.SUBJECT), + "" } + ); + } + } else { + if (subject != null) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "cloned to reqID: " + + clonedRequest.getRequestId().toString(), + subject, + "" } + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + r.getRequestType(), + r.getRequestId(), + initiative, + authMgr, + "cloned to reqID: " + + clonedRequest.getRequestId().toString() } + ); + } + } + + // store a message in the signed audit log file + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } + } + + // add authority names to know what privileges can be requested. + if (CMS.getSubsystem("kra") != null) + header.addStringValue("localkra", "yes"); + if (CMS.getSubsystem("ca") != null) + header.addStringValue("localca", "yes"); + if (CMS.getSubsystem("ra") != null) + header.addStringValue("localra", "yes"); + + header.addBigIntegerValue("seqNum", seqNum, 10); + mParser.fillRequestIntoArg(locale, r, argSet, header); + String rid = r.getExtDataInString(IRequest.REMOTE_REQID); + + if (rid != null) + header.addStringValue("remoteReqID", rid); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[2]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[2]); + + audit(auditMessage); + } + } + + throw e; + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[3]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[3]); + + audit(auditMessage); + } + } + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_ISSUED_CERT_ERROR")); + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[4]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[4]); + + audit(auditMessage); + } + } + + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_ENCODING_ISSUED_CERT_ERROR")); + } catch (NoSuchAlgorithmException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + + // store a message in the signed audit log file + if (toDo != null) { + if (toDo.equals(SIGNED_AUDIT_CLONING)) { + // ("agent" cert request for "cloning") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_NON_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditServiceID, + auditCertificateSubjectName); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_ACCEPTANCE)) { + // (manual "agent" cert request processed - "accepted") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_CANCELLATION)) { + // (manual "agent" cert request processed - "cancelled") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_CANCELLATION_REASON[5]); + + audit(auditMessage); + } else if (toDo.equals(SIGNED_AUDIT_REJECTION)) { + // (manual "agent" cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditInfoName, + SIGNED_AUDIT_MANUAL_REJECTION_REASON[5]); + + audit(auditMessage); + } + } + + throw new EBaseException(CMS.getUserMessage(locale, "CMS_BASE_INTERNAL_ERROR", e.toString())); + } + return; + } + + private void updateNSExtension(HttpServletRequest req, + NSCertTypeExtension ext) throws IOException { + try { + + if (req.getParameter("certTypeSSLServer") == null) { + ext.set(NSCertTypeExtension.SSL_SERVER, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.SSL_SERVER, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeSSLClient") == null) { + ext.set(NSCertTypeExtension.SSL_CLIENT, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.SSL_CLIENT, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeEmail") == null) { + ext.set(NSCertTypeExtension.EMAIL, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.EMAIL, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeObjSigning") == null) { + ext.set(NSCertTypeExtension.OBJECT_SIGNING, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.OBJECT_SIGNING, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeEmailCA") == null) { + ext.set(NSCertTypeExtension.EMAIL_CA, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.EMAIL_CA, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeSSLCA") == null) { + ext.set(NSCertTypeExtension.SSL_CA, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.SSL_CA, Boolean.valueOf(true)); + } + + if (req.getParameter("certTypeObjSigningCA") == null) { + ext.set(NSCertTypeExtension.OBJECT_SIGNING_CA, Boolean.valueOf(false)); + } else { + ext.set(NSCertTypeExtension.OBJECT_SIGNING_CA, Boolean.valueOf(true)); + } + } catch (CertificateException e) { + } + } + + /** + * This method sets extensions parameter into the request so + * that the NSCertTypeExtension policy creates new + * NSCertTypExtension with this setting. Note that this + * setting will not be used if the NSCertType Extension + * already exist in CertificateExtension. In that case, + * updateExtensions() will be called to set the extension + * parameter into the extension directly. + */ + private int updateExtensionsInRequest(HttpServletRequest req, IRequest r) { + int nChanges = 0; + + if (req.getParameter("certTypeSSLServer") != null) { + r.setExtData(NSCertTypeExtension.SSL_SERVER, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.SSL_SERVER); + nChanges++; + } + + if (req.getParameter("certTypeSSLClient") != null) { + r.setExtData(NSCertTypeExtension.SSL_CLIENT, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.SSL_CLIENT); + nChanges++; + } + + if (req.getParameter("certTypeEmail") != null) { + r.setExtData(NSCertTypeExtension.EMAIL, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.EMAIL); + nChanges++; + } + + if (req.getParameter("certTypeObjSigning") != null) { + r.setExtData(NSCertTypeExtension.OBJECT_SIGNING, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.OBJECT_SIGNING); + nChanges++; + } + + if (req.getParameter("certTypeEmailCA") != null) { + r.setExtData(NSCertTypeExtension.EMAIL_CA, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.EMAIL_CA); + nChanges++; + } + + if (req.getParameter("certTypeSSLCA") != null) { + r.setExtData(NSCertTypeExtension.SSL_CA, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.SSL_CA); + nChanges++; + } + + if (req.getParameter("certTypeObjSigningCA") != null) { + r.setExtData(NSCertTypeExtension.OBJECT_SIGNING_CA, "true"); + nChanges++; + } else { + r.deleteExtData(NSCertTypeExtension.OBJECT_SIGNING_CA); + nChanges++; + } + + return nChanges; + } + + protected static final String GRANT_ERROR = "grantError"; + + public static final String GRANT_TRUSTEDMGR_PRIVILEGE = "grantTrustedManagerPrivilege"; + public static final String GRANT_CMAGENT_PRIVILEGE = "grantCMAgentPrivilege"; + public static final String GRANT_RMAGENT_PRIVILEGE = "grantRMAgentPrivilege"; + public static final String GRANT_DRMAGENT_PRIVILEGE = "grantDRMAgentPrivilege"; + public static final String GRANT_UID = "grantUID"; + public static final String GRANT_PRIVILEGE = "grantPrivilege"; + + protected int grant_privileges( + CMSRequest cmsReq, IRequest req, Certificate[] certs, IArgBlock header) + throws EBaseException { + // get privileges to grant + IArgBlock httpParams = cmsReq.getHttpParams(); + + boolean grantTrustedMgr = + httpParams.getValueAsBoolean(GRANT_TRUSTEDMGR_PRIVILEGE, false); + boolean grantRMAgent = + httpParams.getValueAsBoolean(GRANT_RMAGENT_PRIVILEGE, false); + boolean grantCMAgent = + httpParams.getValueAsBoolean(GRANT_CMAGENT_PRIVILEGE, false); + boolean grantDRMAgent = + httpParams.getValueAsBoolean(GRANT_DRMAGENT_PRIVILEGE, false); + + if (!grantTrustedMgr && + !grantCMAgent && !grantRMAgent && !grantDRMAgent) { + return 0; + } else { + IAuthToken authToken = getAuthToken(req); + AuthzToken authzToken = null; + String resourceName = "certServer." + mAuthority.getId() + ".group"; + + try { + authzToken = authorize(mAclMethod, authToken, + resourceName, "add"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + String[] obj = new String[1]; + + if (grantTrustedMgr) + obj[0] = TRUSTED_RA_GROUP; + else if (grantRMAgent) + obj[0] = RA_AGENT_GROUP; + else if (grantCMAgent) + obj[0] = CA_AGENT_GROUP; + else if (grantDRMAgent) + obj[0] = KRA_AGENT_GROUP; + else + obj[0] = "unknown group"; + + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_UNAUTHORIZED_CREATE_GROUP", obj[0])); + } + } + + String uid = (String) httpParams.getValueAsString(GRANT_UID, null); + + if (uid == null || uid.length() == 0) { + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_MISSING_GRANT_UID")); + } + header.addStringValue(GRANT_UID, uid); + + String groupname = null, groupname1 = null; + String userType = ""; + + if (grantTrustedMgr) { + groupname = TRUSTED_RA_GROUP; + userType = Constants.PR_SUBSYSTEM_TYPE; + } else { + if (grantCMAgent) + groupname = CA_AGENT_GROUP; + else if (grantRMAgent) + groupname = RA_AGENT_GROUP; + + if (grantDRMAgent) { + if (groupname != null) + groupname1 = KRA_AGENT_GROUP; + else + groupname = KRA_AGENT_GROUP; + } + userType = Constants.PR_AGENT_TYPE; + } + + String privilege = + (groupname1 == null) ? groupname : groupname + " and " + groupname1; + + header.addStringValue(GRANT_PRIVILEGE, privilege); + + IUGSubsystem ug = (IUGSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_UG); + IUser user = ug.createUser(uid); + + user.setFullName(uid); + user.setEmail(""); + user.setPhone(""); + user.setPassword(""); + user.setUserType(userType); + user.setState("1"); + IGroup group = ug.findGroup(groupname), group1 = null; + + if (group == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_FIND_GROUP_1", groupname)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_FIND_GROUP_ERROR", groupname)); + } + if (groupname1 != null) { + group1 = ug.findGroup(groupname1); + if (group1 == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_FIND_GROUP_1", groupname)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_FIND_GROUP_ERROR", groupname1)); + } + } + try { + ug.addUser(user); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_ADDING_USER_1", uid)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_USER_ERROR", uid)); + } + try { + if (certs[0] instanceof X509CertImpl) { + X509CertImpl tmp[] = (X509CertImpl[]) certs; + + user.setX509Certificates(tmp); + } + + ug.addUserCert(user); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERROR_ADDING_CERT_1", uid)); + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_CERT_ERROR", uid)); + } + try { + group.addMemberName(uid); + ug.modifyGroup(group); + // for audit log + SessionContext sContext = SessionContext.getContext(); + String adminId = (String) sContext.get(SessionContext.USER_ID); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP, + AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT, + new Object[] { adminId, uid, groupname } + ); + + if (group1 != null) { + group1.addMemberName(uid); + ug.modifyGroup(group1); + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_USRGRP, + AuditFormat.LEVEL, AuditFormat.ADDUSERGROUPFORMAT, + new Object[] { adminId, uid, groupname1 } + ); + + } + } catch (Exception e) { + String msg = + "Could not add user " + uid + " to group " + groupname; + + if (group1 != null) + msg += " or group " + groupname1; + log(ILogger.LL_FAILURE, msg); + if (group1 == null) + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_MEMBER", uid, groupname)); + else + throw new ECMSGWException(CMS.getUserMessage("CMS_GW_ADDING_MEMBER_1", uid, groupname, groupname1)); + } + return 1; + } + + /** + * Signed Audit Log Info Name + * + * This method is called to obtain the "InfoName" for + * a signed audit log message. + * <P> + * + * @param type signed audit log request processing type + * @return id string containing the signed audit log message InfoName + */ + private String auditInfoName(String type) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters (this is done below) + + String infoName = ILogger.UNIDENTIFIED; + + if (mSignedAuditLogger == null) { + return infoName; + } + + if (type != null) { + type = type.trim(); + + if (type.equals(SIGNED_AUDIT_ACCEPTANCE)) { + infoName = ILogger.SIGNED_AUDIT_ACCEPTANCE; + } else if (type.equals(SIGNED_AUDIT_CANCELLATION)) { + infoName = ILogger.SIGNED_AUDIT_CANCELLATION; + } else if (type.equals(SIGNED_AUDIT_REJECTION)) { + infoName = ILogger.SIGNED_AUDIT_REJECTION; + } + } + + return infoName; + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param 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 = Utils.base64encode(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (base64Data.substring(i, i).getBytes() != EOL) { + sb.append(base64Data.substring(i, i)); + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } +} + +class RAReqCompletedFiller extends ImportCertsTemplateFiller { + private static final String RA_AGENT_GROUP = "Registration Manager Agents"; + private static final String KRA_AGENT_GROUP = "Data Recovery Manager Agents"; + + public RAReqCompletedFiller() { + super(); + } + + public CMSTemplateParams getTemplateParams( + CMSRequest cmsReq, IAuthority authority, Locale locale, Exception e) + throws Exception { + + Object[] results = (Object[]) cmsReq.getResult(); + Object grantError = results[1]; + //X509CertImpl[] issuedCerts = (X509CertImpl[])results[0]; + Certificate[] issuedCerts = (Certificate[]) results[0]; + + cmsReq.setResult(issuedCerts); + CMSTemplateParams params = + super.getTemplateParams(cmsReq, authority, locale, e); + + if (grantError != null) { + IArgBlock header = params.getHeader(); + + if (grantError instanceof String) { + header.addStringValue( + ProcessCertReq.GRANT_ERROR, (String) grantError); + } else { + EBaseException ex = (EBaseException) grantError; + + header.addStringValue( + ProcessCertReq.GRANT_ERROR, ex.toString(locale)); + } + IArgBlock httpParams = cmsReq.getHttpParams(); + String uid = httpParams.getValueAsString( + ProcessCertReq.GRANT_UID, null); + + header.addStringValue(ProcessCertReq.GRANT_UID, uid); + boolean grantRMAgent = httpParams.getValueAsBoolean( + ProcessCertReq.GRANT_RMAGENT_PRIVILEGE, false); + boolean grantDRMAgent = httpParams.getValueAsBoolean( + ProcessCertReq.GRANT_DRMAGENT_PRIVILEGE, false); + String privilege = null; + + if (grantRMAgent) { + privilege = RA_AGENT_GROUP; + } + if (grantDRMAgent) { + if (privilege != null) + privilege += " and " + KRA_AGENT_GROUP; + else + privilege = KRA_AGENT_GROUP; + } + header.addStringValue(ProcessCertReq.GRANT_PRIVILEGE, privilege); + } + return params; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java b/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java new file mode 100644 index 000000000..9c173d832 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java @@ -0,0 +1,334 @@ +// --- 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.request; + +import java.io.IOException; +import java.util.Locale; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.X509CertImpl; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Display Generic Request detail to the user. + * + * @version $Revision$, $Date$ + */ +public class ProcessReq extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = -6941843162486565610L; + private final static String INFO = "processReq"; + private final static String SEQNUM = "seqNum"; + private final static String DO_ASSIGN = "doAssign"; + private final static String TPL_FILE = "processReq.template"; + private final static String OUT_ERROR = "errorDetails"; + private final static String PROP_PARSER = "parser"; + + private IRequestQueue mQueue = null; + private String mFormPath = null; + private IReqParser mParser = null; + private String[] mSigningAlgorithms = null; + + private static String[] DEF_SIGNING_ALGORITHMS = new String[] + { "SHA1withRSA", "SHA256withRSA", "SHA512withRSA", "SHA1withDSA", "MD5withRSA", "MD2withRSA" }; + + /** + * Process request. + */ + public ProcessReq() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "processReq.template" to process the response. + * The initialization parameter 'parser' is read from the + * servlet configration, and is used to set the type of request. + * The value of this parameter can be: + * <UL> + * <LI><B>CertReqParser.NODETAIL_PARSER</B> - Show certificate Summary + * <LI><B>CertReqParser.DETAIL_PARSER</B> - Show certificate detail + * <LI><B>KeyReqParser.PARSER</B> - Show key archival detail + * </UL> + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mQueue = mAuthority.getRequestQueue(); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + String tmp = sc.getInitParameter(PROP_PARSER); + + if (tmp != null) { + if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER")) + mParser = CertReqParser.NODETAIL_PARSER; + else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER")) + mParser = CertReqParser.DETAIL_PARSER; + else if (tmp.trim().equals("KeyReqParser.PARSER")) + mParser = KeyReqParser.PARSER; + } + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param seqNum + * <li>http.param doAssign reassign request. Value can be reassignToMe reassignToNobody + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + BigInteger seqNum = BigInteger.ONE.negate(); + + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + + IArgBlock header = CMS.createArgBlock(); + IArgBlock fixed = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, fixed); + + String doAssign = null; + EBaseException error = null; + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + "Error getting template " + mFormPath + " Error " + e); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + if (req.getParameter(SEQNUM) != null) { + seqNum = new BigInteger(req.getParameter(SEQNUM)); + } + doAssign = req.getParameter(DO_ASSIGN); + + if (seqNum.compareTo(BigInteger.ONE.negate()) > 0) { + // start authorization + AuthzToken authzToken = null; + + try { + if (doAssign == null) { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "read"); + } else if (doAssign.equals("toMe") || + doAssign.equals("reassignToMe")) { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "assign"); + } else if (doAssign.equals("reassignToNobody")) { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "unassign"); + } + } 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + process(argSet, header, seqNum, req, resp, + doAssign, locale[0]); + } else { + log(ILogger.LL_FAILURE, "Invalid sequence number " + seqNum); + error = new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + String.valueOf(seqNum))); + } + } catch (EBaseException e) { + error = e; + } catch (NumberFormatException e) { + error = new EBaseException(CMS.getUserMessage(locale[0], "CMS_BASE_INVALID_NUMBER_FORMAT")); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + cmsReq.setStatus(CMSRequest.SUCCESS); + } + } else { + cmsReq.setError(error); + cmsReq.setStatus(CMSRequest.ERROR); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + "Error getting servlet output stream for rendering template. " + + "Error " + e); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + return; + } + + /** + * Sends request information to the calller. + * returns whether there was an error or not. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + BigInteger seqNum, HttpServletRequest req, + HttpServletResponse resp, + String doAssign, Locale locale) + throws EBaseException { + + header.addBigIntegerValue("seqNum", seqNum, 10); + + IRequest r = mQueue.findRequest(new RequestId(seqNum)); + + if (r != null) { + if (doAssign != null) { + if ((doAssign.equals("toMe")) + || (doAssign.equals("reassignToMe"))) { + SessionContext ctx = SessionContext.getContext(); + String id = (String) ctx.get(SessionContext.USER_ID); + + r.setRequestOwner(id); + mQueue.updateRequest(r); + } else if (doAssign.equals("reassignToNobody")) { + r.setRequestOwner(null); + mQueue.updateRequest(r); + } + } + + // add authority names to know what privileges can be requested. + if (CMS.getSubsystem("kra") != null) + header.addStringValue("localkra", "yes"); + if (CMS.getSubsystem("ca") != null) + header.addStringValue("localca", "yes"); + if (CMS.getSubsystem("ra") != null) + header.addStringValue("localra", "yes"); + + // DONT NEED TO DO THIS FOR DRM + if (mAuthority instanceof ICertAuthority) { + // Check/set signing algorithms dynamically. + // In RA mSigningAlgorithms could be null at startup if CA is not + // up and set later when CA comes back up. + // Once it's set assumed that it won't change. + String[] allAlgorithms = mSigningAlgorithms; + + if (allAlgorithms == null) { + allAlgorithms = mSigningAlgorithms = + ((ICertAuthority) mAuthority).getCASigningAlgorithms(); + if (allAlgorithms == null) { + CMS.debug( + "ProcessReq: signing algorithms set to All algorithms"); + allAlgorithms = AlgorithmId.ALL_SIGNING_ALGORITHMS; + } else + CMS.debug( + "ProcessReq: First signing algorithms is " + allAlgorithms[0]); + } + String validAlgorithms = null; + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < allAlgorithms.length; i++) { + if (i > 0) { + sb.append("+"); + sb.append(allAlgorithms[i]); + } else { + sb.append(allAlgorithms[i]); + } + } + validAlgorithms = sb.toString(); + if (validAlgorithms != null) + header.addStringValue("validAlgorithms", validAlgorithms); + if (mAuthority instanceof ICertificateAuthority) { + String signingAlgorithm = ((ICertificateAuthority) mAuthority).getDefaultAlgorithm(); + + if (signingAlgorithm != null) + header.addStringValue("caSigningAlgorithm", signingAlgorithm); + header.addLongValue("defaultValidityLength", + ((ICertificateAuthority) mAuthority).getDefaultValidity() / 1000); + } else if (mAuthority instanceof IRegistrationAuthority) { + header.addLongValue("defaultValidityLength", + ((IRegistrationAuthority) mAuthority).getDefaultValidity() / 1000); + } + X509CertImpl caCert = ((ICertAuthority) mAuthority).getCACert(); + + if (caCert != null) { + int caPathLen = caCert.getBasicConstraints(); + + header.addIntegerValue("caPathLen", caPathLen); + } + } + + mParser.fillRequestIntoArg(locale, r, argSet, header); + } else { + log(ILogger.LL_FAILURE, "Invalid sequence number " + seqNum.toString()); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + seqNum.toString())); + } + + return; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/QueryReq.java b/base/common/src/com/netscape/cms/servlet/request/QueryReq.java new file mode 100644 index 000000000..f6ae634f4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/QueryReq.java @@ -0,0 +1,558 @@ +// --- 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.request; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; +import java.math.BigInteger; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.IRequestVirtualList; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Show paged list of requests matching search criteria + * + * @version $Revision$, $Date$ + */ +public class QueryReq extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = -8729364426329835378L; + // constants + private final static String INFO = "QueryReq"; + private final static String IN_SHOW_ALL = "showAll"; + private final static String IN_SHOW_WAITING = "showWaiting"; + private final static String IN_SHOW_IN_SERVICE = "showInService"; + private final static String IN_SHOW_PENDING = "showPending"; + private final static String IN_SHOW_CANCELLED = "showCancelled"; + private final static String IN_SHOW_REJECTED = "showRejected"; + private final static String IN_SHOW_COMPLETED = "showCompleted"; + private final static String IN_MAXCOUNT = "maxCount"; + private final static String IN_TOTALCOUNT = "totalRecordCount"; + private final static String ON = "on"; + private final static String PROP_PARSER = "parser"; + + private final static String TPL_FILE = "queryReq.template"; + + private final static String OUT_SERVICE_URL = "serviceURL"; + private final static String OUT_OP = "op"; + private final static String OUT_MAXCOUNT = IN_MAXCOUNT; + private final static String OUT_TOTALCOUNT = IN_TOTALCOUNT; + private final static String OUT_CURRENTCOUNT = "currentRecordCount"; + private final static String OUT_SENTINEL_DOWN = "querySentinelDown"; + private final static String OUT_SHOW_COMPLETED = IN_SHOW_COMPLETED; + private final static String OUT_SEQNUM = "seqNum"; + private final static String OUT_STATUS = "status"; + private final static String OUT_CREATE_ON = "createdOn"; + private final static String OUT_UPDATE_ON = "updatedOn"; + private final static String OUT_UPDATE_BY = "updatedBy"; + private final static String OUT_REQUESTING_USER = "requestingUser"; + //keeps track of where to begin if page down + private final static String OUT_FIRST_ENTRY_ON_PAGE = "firstEntryOnPage"; + //keeps track of where to begin if page up + private final static String OUT_LAST_ENTRY_ON_PAGE = "lastEntryOnPage"; + private final static String OUT_SUBJECT = "subject"; + private final static String OUT_REQUEST_TYPE = "requestType"; + private final static String OUT_COMMENTS = "requestorComments"; + private final static String OUT_SERIALNO = "serialNumber"; + private final static String OUT_OWNER_NAME = "ownerName"; + private final static String OUT_PUBLIC_KEY_INFO = + "subjectPublicKeyInfo"; + private final static String OUT_ERROR = "error"; + private final static String OUT_AUTHORITY_ID = "authorityid"; + + // variables + private IReqParser mParser = null; + private IRequestQueue mQueue = null; + private String mFormPath = null; + private int mMaxReturns = 2000; + + public CMSRequest newCMSRequest() { + return new CMSRequest(); + } + + /** + * Constructor + */ + public QueryReq() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "queryReq.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); + mQueue = mAuthority.getRequestQueue(); + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + try { + mMaxReturns = Integer.parseInt(sc.getInitParameter("maxResults")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + + String tmp = sc.getInitParameter(PROP_PARSER); + + if (tmp != null) { + if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER")) + mParser = CertReqParser.NODETAIL_PARSER; + else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER")) + mParser = CertReqParser.DETAIL_PARSER; + else if (tmp.trim().equals("KeyReqParser.PARSER")) + mParser = KeyReqParser.PARSER; + } + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + private String getRequestType(String p) { + String filter = "(requestType=*)"; + + if (p == null) + return filter; + if (p.equals(IRequest.ENROLLMENT_REQUEST)) { + filter = "(requestType=" + IRequest.ENROLLMENT_REQUEST + ")"; + } else if (p.equals(IRequest.RENEWAL_REQUEST)) { + filter = "(requestType=" + IRequest.RENEWAL_REQUEST + ")"; + } else if (p.equals(IRequest.REVOCATION_REQUEST)) { + filter = "(requestType=" + IRequest.REVOCATION_REQUEST + ")"; + } else if (p.equals(IRequest.UNREVOCATION_REQUEST)) { + filter = "(requestType=" + IRequest.UNREVOCATION_REQUEST + ")"; + } else if (p.equals(IRequest.KEYARCHIVAL_REQUEST)) { + filter = "(requestType=" + IRequest.KEYARCHIVAL_REQUEST + ")"; + } else if (p.equals(IRequest.KEYRECOVERY_REQUEST)) { + filter = "(requestType=" + IRequest.KEYRECOVERY_REQUEST + ")"; + } else if (p.equals(IRequest.GETCACHAIN_REQUEST)) { + filter = "(requestType=" + IRequest.GETCACHAIN_REQUEST + ")"; + } else if (p.equals(IRequest.GETREVOCATIONINFO_REQUEST)) { + filter = "(requestType=" + IRequest.GETREVOCATIONINFO_REQUEST + ")"; + } else if (p.equals(IRequest.GETCRL_REQUEST)) { + filter = "(requestType=" + IRequest.GETCRL_REQUEST + ")"; + } else if (p.equals(IRequest.GETCERTS_REQUEST)) { + filter = "(requestType=" + IRequest.GETCERTS_REQUEST + ")"; + } else if (p.equals(IRequest.NETKEY_KEYGEN_REQUEST)) { + filter = "(requestType=" + IRequest.NETKEY_KEYGEN_REQUEST + ")"; + } else if (p.equals(IN_SHOW_ALL)) { + filter = "(requestType=*)"; + } + return filter; + } + + private String getRequestState(String p) { + String filter = "(requeststate=*)"; + + if (p == null) + return filter; + if (p.equals(IN_SHOW_WAITING)) { + filter = "(requeststate=pending)"; + } else if (p.equals(IN_SHOW_IN_SERVICE)) { + filter = "(requeststate=svc_pending)"; + } else if (p.equals(IN_SHOW_PENDING)) { + filter = "(requeststate=pending)"; + } else if (p.equals(IN_SHOW_CANCELLED)) { + filter = "(requeststate=canceled)"; + } else if (p.equals(IN_SHOW_REJECTED)) { + filter = "(requeststate=rejected)"; + } else if (p.equals(IN_SHOW_COMPLETED)) { + filter = "(requeststate=complete)"; + } else if (p.equals(IN_SHOW_ALL)) { + filter = "(requeststate=*)"; + } + return filter; + } + + /** + * Process the HTTP request. + * <ul> + * <li>http.param reqState request state (one of showAll, showWaiting, showInService, showCancelled, showRejected, + * showCompleted) + * <li>http.param reqType + * <li>http.param seqNumFromDown request ID to start at (decimal, or hex if when paging down seqNumFromDown starts + * with 0x) + * <li>http.param seqNumFromUp request ID to start at (decimal, or hex if when paging up seqNumFromUp starts with + * 0x) + * <li>http.param maxCount maximum number of records to show + * <li>http.param totalCount total number of records in set of pages + * <li>http.param direction "up", "down", "begin", or "end" + * </ul> + * + * @param cmsReq the object holding the request and response information + */ + + public void process(CMSRequest cmsReq) throws EBaseException { + CMS.debug("in QueryReq servlet"); + + // Authentication / Authorization + + HttpServletRequest req = cmsReq.getHttpReq(); + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + // if get a EBaseException we just throw it. + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", mFormPath, e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + /** + * WARNING: + * + * PLEASE DO NOT TOUCH THE FILTER HERE. ALL FILTERS ARE INDEXED. + * + **/ + String filter = null; + String reqState = req.getParameter("reqState"); + String reqType = req.getParameter("reqType"); + + if (reqState == null || reqType == null) { + filter = "(requeststate=*)"; + } else if (reqState.equals(IN_SHOW_ALL) && + reqType.equals(IN_SHOW_ALL)) { + filter = "(requeststate=*)"; + } else if (reqState.equals(IN_SHOW_ALL)) { + filter = getRequestType(reqType); + } else if (reqType.equals(IN_SHOW_ALL)) { + filter = getRequestState(reqState); + } else { + filter = "(&" + getRequestState(reqState) + + getRequestType(reqType) + ")"; + } + + String direction = "begin"; + if (req.getParameter("direction") != null) { + direction = req.getParameter("direction").trim(); + } + + BigInteger top = BigInteger.ZERO; + BigInteger bottom = BigInteger.ZERO; + + try { + String top_s = req.getParameter(OUT_FIRST_ENTRY_ON_PAGE); + if (top_s == null) + top_s = "0"; + + String bottom_s = req.getParameter(OUT_LAST_ENTRY_ON_PAGE); + if (bottom_s == null) + bottom_s = "0"; + + if (top_s.trim().startsWith("0x")) { + top = new BigInteger(top_s.trim().substring(2), 16); + } else { + top = new BigInteger(top_s.trim()); + } + if (bottom_s.trim().startsWith("0x")) { + bottom = new BigInteger(bottom_s.trim().substring(2), 16); + } else { + bottom = new BigInteger(bottom_s.trim()); + } + + } catch (NumberFormatException e) { + + } + + // avoid NumberFormatException to the user interface + int maxCount = 10; + try { + maxCount = Integer.parseInt(req.getParameter(IN_MAXCOUNT)); + } catch (Exception e) { + } + if (maxCount > mMaxReturns) { + CMS.debug("Resetting page size from " + maxCount + " to " + mMaxReturns); + maxCount = mMaxReturns; + } + + HttpServletResponse resp = cmsReq.getHttpResp(); + CMSTemplateParams argset = doSearch(locale[0], filter, maxCount, direction, top, bottom); + + argset.getFixed().addStringValue("reqType", reqType); + argset.getFixed().addStringValue("reqState", reqState); + argset.getFixed().addIntegerValue("maxCount", maxCount); + + try { + form.getOutput(argset); + resp.setContentType("text/html"); + form.renderOutput(resp.getOutputStream(), argset); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + cmsReq.setStatus(CMSRequest.SUCCESS); + return; + } + + /** + * Perform search based on direction button pressed + * + * @param filter ldap filter indicating which VLV to search through. This can be + * 'all requests', 'pending', etc + * @param count the number of requests to show per page + * @param direction either 'begin', 'end', 'previous' or 'next' (defaults to end) + * @param top the number of the request shown on at the top of the current page + * @param bottom the number of the request shown on at the bottom of the current page + * @return + */ + + private CMSTemplateParams doSearch(Locale l, String filter, + int count, String direction, BigInteger top, BigInteger bottom) { + CMSTemplateParams ctp = null; + if (direction.equals("previous")) { + ctp = doSearch(l, filter, -count, top); + } else if (direction.equals("next")) { + bottom = bottom.add(BigInteger.ONE); + ctp = doSearch(l, filter, count, bottom); + } else if (direction.equals("begin")) { + ctp = doSearch(l, filter, count, BigInteger.ZERO); + } else if (direction.equals("first")) { + ctp = doSearch(l, filter, count, bottom); + } else { // if 'direction is 'end', default here + ctp = doSearch(l, filter, -count, BigInteger.ONE.negate()); + } + return ctp; + } + + /** + * + * @param locale + * @param filter the types of requests to return - this must match the VLV index + * @param count maximum number of records to return + * @param marker indication of the request ID where the page is anchored + * @return + */ + + private CMSTemplateParams doSearch( + Locale locale, + String filter, + int count, + BigInteger marker) { + + IArgBlock header = CMS.createArgBlock(); + IArgBlock context = CMS.createArgBlock(); + CMSTemplateParams argset = new CMSTemplateParams(header, context); + + try { + long startTime = CMS.getCurrentDate().getTime(); + // preserve the type of request that we are + // requesting. + + header.addStringValue(OUT_AUTHORITY_ID, mAuthority.getId()); + header.addStringValue(OUT_REQUESTING_USER, "admin"); + + boolean jumptoend = false; + if (marker.toString().equals("-1")) { + marker = BigInteger.ZERO; // I think this is inconsequential + jumptoend = true; // override to '99' during search + } + + RequestId id = new RequestId(marker); + IRequestVirtualList list = mQueue.getPagedRequestsByFilter( + id, + jumptoend, + filter, + ((count < 0) ? count - 1 : count + 1), + "requestId"); + + int maxCount = 0; + if (count < 0 && jumptoend) { + maxCount = -count; + } else if (count < 0) { + maxCount = -count + 1; + } else { + maxCount = count; + } + int totalCount = (jumptoend) ? maxCount : + (list.getSize() - list.getCurrentIndex()); + header.addIntegerValue(OUT_TOTALCOUNT, totalCount); + header.addIntegerValue(OUT_CURRENTCOUNT, list.getSize()); + + Vector<IRequest> v = fetchRecords(list, maxCount); + v = normalizeOrder(v); + trim(v, id); + + int currentCount = 0; + BigInteger curNum = BigInteger.ZERO; + BigInteger firstNum = BigInteger.ONE.negate(); + Enumeration<IRequest> requests = v.elements(); + + while (requests.hasMoreElements()) { + IRequest request = null; + try { + request = requests.nextElement(); + } catch (Exception e) { + CMS.debug("Error displaying request:" + e.getMessage()); + // handled below + } + if (request == null) { + log(ILogger.LL_WARN, "Error display request on page"); + continue; + } + + curNum = new BigInteger(request.getRequestId().toString()); + + if (firstNum.equals(BigInteger.ONE.negate())) { + firstNum = curNum; + } + + IArgBlock rec = CMS.createArgBlock(); + mParser.fillRequestIntoArg(locale, request, argset, rec); + mQueue.releaseRequest(request); + argset.addRepeatRecord(rec); + + currentCount++; + + }// while + long endTime = CMS.getCurrentDate().getTime(); + + header.addIntegerValue(OUT_CURRENTCOUNT, currentCount); + header.addStringValue("time", Long.toString(endTime - startTime)); + header.addBigIntegerValue(OUT_FIRST_ENTRY_ON_PAGE, firstNum, 10); + header.addBigIntegerValue(OUT_LAST_ENTRY_ON_PAGE, curNum, 10); + + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } catch (Exception e) { + } + return argset; + } + + /** + * If the vector contains the marker element at the end, remove it. + * + * @param v The vector to trim + * @param marker the marker to look for. + */ + private void trim(Vector<IRequest> v, RequestId marker) { + int i = v.size() - 1; + if (v.elementAt(i).getRequestId().toString().equals( + marker.toString())) { + v.remove(i); + } + } + + /** + * Sometimes the list comes back from LDAP in reverse order. This function makes + * sure the results are in 'forward' order. + * + * @param list + * @return + */ + private Vector<IRequest> fetchRecords(IRequestVirtualList list, int maxCount) { + + Vector<IRequest> v = new Vector<IRequest>(); + int count = list.getSize(); + int c = 0; + for (int i = 0; i < count; i++) { + IRequest request = list.getElementAt(i); + if (request != null) { + v.add(request); + c++; + } + if (c >= maxCount) + break; + } + + return v; + + } + + /** + * If the requests are in backwards order, reverse the list + * + * @param list + * @return + */ + private Vector<IRequest> normalizeOrder(Vector<IRequest> list) { + + BigInteger firstrequestnum = new BigInteger(list.elementAt(0) + .getRequestId().toString()); + BigInteger lastrequestnum = new BigInteger(list.elementAt(list + .size() - 1).getRequestId().toString()); + boolean reverse = false; + if (firstrequestnum.compareTo(lastrequestnum) > 0) { + reverse = true; // if the order is backwards, place items at the beginning + } + Vector<IRequest> v = new Vector<IRequest>(); + int count = list.size(); + for (int i = 0; i < count; i++) { + IRequest request = list.elementAt(i); + if (request != null) { + if (reverse) + v.add(0, request); + else + v.add(request); + } + } + + return v; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/ReqParser.java b/base/common/src/com/netscape/cms/servlet/request/ReqParser.java new file mode 100644 index 000000000..230ddb433 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/ReqParser.java @@ -0,0 +1,79 @@ +// --- 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.request; + +import java.util.Locale; +import java.math.BigInteger; + +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cms.servlet.common.CMSTemplateParams; + +/** + * A class representing a request parser. + * <P> + * + * @version $Revision$, $Date$ + */ +public class ReqParser implements IReqParser { + + private final static String TYPE = "requestType"; + private final static String STATUS = "status"; + private final static String CREATE_ON = "createdOn"; + private final static String UPDATE_ON = "updatedOn"; + private final static String UPDATE_BY = "updatedBy"; + + /** + * Constructs a request parser. + */ + public ReqParser() { + } + + /** + * Maps request object into argument block. + */ + public void fillRequestIntoArg(Locale l, IRequest req, CMSTemplateParams argSet, IArgBlock arg) + throws EBaseException { + arg.addStringValue(TYPE, req.getRequestType()); + arg.addBigIntegerValue("seqNum", + new BigInteger(req.getRequestId().toString()), 10); + arg.addStringValue(STATUS, + req.getRequestStatus().toString()); + arg.addLongValue(CREATE_ON, + req.getCreationTime().getTime() / 1000); + arg.addLongValue(UPDATE_ON, + req.getModificationTime().getTime() / 1000); + String updatedBy = req.getExtDataInString(IRequest.UPDATED_BY); + + if (updatedBy == null) + updatedBy = ""; + arg.addStringValue(UPDATE_BY, updatedBy); + + SessionContext ctx = SessionContext.getContext(); + String id = (String) ctx.get(SessionContext.USER_ID); + + arg.addStringValue("callerName", id); + + String owner = req.getRequestOwner(); + + if (owner != null) + arg.addStringValue("assignedTo", owner); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java b/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java new file mode 100644 index 000000000..08d5805b6 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java @@ -0,0 +1,336 @@ +// --- 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.request; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Date; +import java.util.Locale; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +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.base.IArgBlock; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestList; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.cms.servlet.common.CMSTemplate; +import com.netscape.cms.servlet.common.CMSTemplateParams; +import com.netscape.cms.servlet.common.ECMSGWException; + +/** + * Search for certificates matching complex query filter + * + * @version $Revision$, $Date$ + */ +public class SearchReqs extends CMSServlet { + + /** + * + */ + private static final long serialVersionUID = 2449481964851735051L; + private final static String TPL_FILE = "queryReq.template"; + private final static String INFO = "QueryReq"; + private final static String PROP_MAX_SEARCH_RETURNS = "maxSearchReqReturns"; + private final static String PROP_PARSER = "parser"; + private final static String CURRENT_TIME = "currentTime"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + private final static String OUT_AUTHORITY_ID = "authorityid"; + private final static String OUT_REQUESTING_USER = "requestingUser"; + private final static String OUT_SEQNUM_FROM = "seqNumFrom"; + private final static String OUT_MAXCOUNT = "maxCount"; + private final static String OUT_TOTALCOUNT = "totalRecordCount"; + private final static String OUT_CURRENTCOUNT = "currentRecordCount"; + private final static String OUT_SENTINEL = "querySentinel"; + private final static String OUT_ERROR = "error"; + private final static int MAX_RESULTS = 1000; + + private IRequestQueue mQueue = null; + private IReqParser mParser = null; + private String mFormPath = null; + private int mMaxReturns = MAX_RESULTS; + private int mTimeLimits = 30; /* in seconds */ + + /** + * Constructs query key servlet. + */ + public SearchReqs() { + super(); + } + + /** + * initialize the servlet. This servlet uses queryReq.template + * to render the response + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + // override success to render own template. + mTemplates.remove(CMSRequest.SUCCESS); + + if (mAuthority instanceof ISubsystem) { + ISubsystem sub = (ISubsystem) mAuthority; + IConfigStore authConfig = sub.getConfigStore(); + + if (authConfig != null) { + try { + mMaxReturns = authConfig.getInteger(PROP_MAX_SEARCH_RETURNS, MAX_RESULTS); + } catch (EBaseException e) { + // do nothing + } + } + } + if (mAuthority instanceof ICertificateAuthority) { + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + mQueue = ca.getRequestQueue(); + } + + mFormPath = "/" + mAuthority.getId() + "/" + TPL_FILE; + + /* Server-Side time limit */ + try { + int maxResults = Integer.parseInt(sc.getInitParameter("maxResults")); + if (maxResults < mMaxReturns) + mMaxReturns = maxResults; + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + try { + mTimeLimits = Integer.parseInt(sc.getInitParameter("timeLimits")); + } catch (Exception e) { + /* do nothing, just use the default if integer parsing failed */ + } + + String tmp = sc.getInitParameter(PROP_PARSER); + + if (tmp != null) { + if (tmp.trim().equals("CertReqParser.NODETAIL_PARSER")) + mParser = CertReqParser.NODETAIL_PARSER; + else if (tmp.trim().equals("CertReqParser.DETAIL_PARSER")) + mParser = CertReqParser.DETAIL_PARSER; + else if (tmp.trim().equals("KeyReqParser.PARSER")) + mParser = KeyReqParser.PARSER; + } + + // override success and error templates to null - + // handle templates locally. + mTemplates.remove(CMSRequest.SUCCESS); + mTemplates.remove(CMSRequest.ERROR); + + if (mOutputTemplatePath != null) + mFormPath = mOutputTemplatePath; + } + + /** + * Serves HTTP request. This format of this request is as follows: + * queryCert? + * [maxCount=<number>] + * [queryFilter=<filter>] + * [revokeAll=<filter>] + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + 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) { + cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + EBaseException error = null; + int maxResults = -1; + int timeLimit = -1; + + IArgBlock header = CMS.createArgBlock(); + IArgBlock ctx = CMS.createArgBlock(); + CMSTemplateParams argSet = new CMSTemplateParams(header, ctx); + + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + try { + form = getTemplate(mFormPath, req, locale); + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_GET_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + + try { + String maxResultsStr = req.getParameter("maxResults"); + + if (maxResultsStr != null && maxResultsStr.length() > 0) + maxResults = Integer.parseInt(maxResultsStr); + String timeLimitStr = req.getParameter("timeLimit"); + + if (timeLimitStr != null && timeLimitStr.length() > 0) + timeLimit = Integer.parseInt(timeLimitStr); + + process(argSet, header, req.getParameter("queryRequestFilter"), authToken, + maxResults, timeLimit, req, resp, locale[0]); + } catch (NumberFormatException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_INVALID_NUMBER_FORMAT")); + error = new EBaseException(CMS.getUserMessage(getLocale(req), "CMS_BASE_INVALID_NUMBER_FORMAT")); + } catch (EBaseException e) { + error = e; + } + + try { + ServletOutputStream out = resp.getOutputStream(); + + if (error == null) { + String xmlOutput = req.getParameter("xml"); + if (xmlOutput != null && xmlOutput.equals("true")) { + outputXML(resp, argSet); + } else { + cmsReq.setStatus(CMSRequest.SUCCESS); + resp.setContentType("text/html"); + form.renderOutput(out, argSet); + } + } else { + cmsReq.setStatus(CMSRequest.ERROR); + cmsReq.setError(error); + } + } catch (IOException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_ERR_OUT_STREAM_TEMPLATE", e.toString())); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_DISPLAY_TEMPLATE_ERROR")); + } + } + + /** + * Process the key search. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + String filter, IAuthToken token, + int maxResults, int timeLimit, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) + throws EBaseException { + + try { + long startTime = CMS.getCurrentDate().getTime(); + + if (filter.indexOf(CURRENT_TIME, 0) > -1) { + filter = insertCurrentTime(filter); + } + + String owner = req.getParameter("owner"); + String requestowner_filter = ""; + String newfilter = ""; + if (owner.length() == 0) { + newfilter = filter; + } else { + if (owner.equals("self")) { + String self_uid = token.getInString(IAuthToken.USER_ID); + requestowner_filter = "(requestowner=" + self_uid + ")"; + } else { + String uid = req.getParameter("uid"); + requestowner_filter = "(requestowner=" + uid + ")"; + } + newfilter = "(&" + requestowner_filter + filter.substring(2); + } + // xxx the filter includes serial number range??? + if (maxResults == -1 || maxResults > mMaxReturns) { + CMS.debug("Resetting maximum of returned results from " + maxResults + " to " + mMaxReturns); + maxResults = mMaxReturns; + } + if (timeLimit == -1 || timeLimit > mTimeLimits) { + CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits); + timeLimit = mTimeLimits; + } + IRequestList list = (timeLimit > 0) ? + mQueue.listRequestsByFilter(newfilter, maxResults, timeLimit) : + mQueue.listRequestsByFilter(newfilter, maxResults); + + int count = 0; + + while (list != null && list.hasMoreElements()) { + IRequest request = (IRequest) list.nextRequestObject(); + + if (request != null) { + count++; + IArgBlock rarg = CMS.createArgBlock(); + mParser.fillRequestIntoArg(locale, request, argSet, rarg); + argSet.addRepeatRecord(rarg); + long endTime = CMS.getCurrentDate().getTime(); + + header.addIntegerValue(OUT_CURRENTCOUNT, count); + header.addStringValue("time", Long.toString(endTime - startTime)); + } + } + header.addIntegerValue(OUT_TOTALCOUNT, count); + } catch (EBaseException e) { + CMS.getLogMessage("CMSGW_ERROR_LISTCERTS", e.toString()); + throw e; + } + return; + } + + private String insertCurrentTime(String filter) { + Date now = null; + StringBuffer newFilter = new StringBuffer(); + int k = 0; + int i = filter.indexOf(CURRENT_TIME, k); + + while (i > -1) { + if (now == null) + now = new Date(); + newFilter.append(filter.substring(k, i)); + newFilter.append(now.getTime()); + k = i + CURRENT_TIME.length(); + i = filter.indexOf(CURRENT_TIME, k); + } + if (k > 0) { + newFilter.append(filter.substring(k, filter.length())); + } + return newFilter.toString(); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/ArchivalRequestData.java b/base/common/src/com/netscape/cms/servlet/request/model/ArchivalRequestData.java new file mode 100644 index 000000000..8a25c6684 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/ArchivalRequestData.java @@ -0,0 +1,123 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +/** + * + */ +package com.netscape.cms.servlet.request.model; + +import javax.ws.rs.core.MultivaluedMap; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +/** + * @author alee + * + */ +@XmlRootElement(name="SecurityDataArchivalRequest") +@XmlAccessorType(XmlAccessType.FIELD) +public class ArchivalRequestData { + + private static final String CLIENT_ID = "clientID"; + private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey"; + private static final String DATA_TYPE = "dataType"; + private static final String WRAPPED_PRIVATE_DATA = "wrappedPrivateData"; + + @XmlElement + protected String clientId; + + @XmlElement + protected String transWrappedSessionKey; + + @XmlElement + protected String dataType; + + @XmlElement + protected String wrappedPrivateData; + + public ArchivalRequestData() { + // required for JAXB (defaults) + } + + public ArchivalRequestData(MultivaluedMap<String, String> form) { + clientId = form.getFirst(CLIENT_ID); + transWrappedSessionKey = form.getFirst(TRANS_WRAPPED_SESSION_KEY); + dataType = form.getFirst(DATA_TYPE); + wrappedPrivateData = form.getFirst(WRAPPED_PRIVATE_DATA); + } + + /** + * @return the clientId + */ + public String getClientId() { + return clientId; + } + + /** + * @param clientId the clientId to set + */ + public void setClientId(String clientId) { + this.clientId = clientId; + } + + /** + * @return the transWrappedSessionKey + */ + public String getTransWrappedSessionKey() { + return transWrappedSessionKey; + } + + /** + * @param transWrappedSessionKey the transWrappedSessionKey to set + */ + public void setTransWrappedSessionKey(String transWrappedSessionKey) { + this.transWrappedSessionKey = transWrappedSessionKey; + } + + /** + * @return the dataType + */ + public String getDataType() { + return dataType; + } + + /** + * @param dataType the dataType to set + */ + public void setDataType(String dataType) { + this.dataType = dataType; + } + + /** + * @return the wrappedPrivateData + */ + public String getWrappedPrivateData() { + return wrappedPrivateData; + } + + /** + * @param wrappedPrivateData the wrappedPrivateData to set + */ + public void setWrappedPrivateData(String wrappedPrivateData) { + this.wrappedPrivateData = wrappedPrivateData; + } + + +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java new file mode 100644 index 000000000..d1f1a27bd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestDAO.java @@ -0,0 +1,326 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.net.URI; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +import javax.ws.rs.Path; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestList; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.IRequestVirtualList; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.cms.servlet.base.model.Link; +import com.netscape.cms.servlet.key.KeyResource; +import com.netscape.cms.servlet.key.model.KeyDAO; +import com.netscape.cms.servlet.key.model.KeyDataInfos; +import com.netscape.certsrv.profile.IEnrollProfile; +import com.netscape.cms.servlet.request.KeyRequestResource; + +/** + * @author alee + * + */ +public class KeyRequestDAO { + private IRequestQueue queue; + private IKeyRecoveryAuthority kra; + + private static String REQUEST_ARCHIVE_OPTIONS = IEnrollProfile.REQUEST_ARCHIVE_OPTIONS; + + private String[] vlvFilters = { + "(requeststate=*)", "(requesttype=enrollment)", + "(requesttype=recovery)", "(requeststate=canceled)", + "(&(requeststate=canceled)(requesttype=enrollment))", + "(&(requeststate=canceled)(requesttype=recovery))", + "(requeststate=rejected)", + "(&(requeststate=rejected)(requesttype=enrollment))", + "(&(requeststate=rejected)(requesttype=recovery))", + "(requeststate=complete)", + "(&(requeststate=complete)(requesttype=enrollment))", + "(&(requeststate=complete)(requesttype=recovery))" + }; + + public static final String ATTR_SERIALNO = "serialNumber"; + + public KeyRequestDAO() { + kra = ( IKeyRecoveryAuthority ) CMS.getSubsystem( "kra" ); + queue = kra.getRequestQueue(); + } + + /** + * Finds list of requests matching the specified search filter. + * + * If the filter corresponds to a VLV search, then that search is executed and the pageSize + * and start parameters are used. Otherwise, the maxResults and maxTime parameters are + * used in the regularly indexed search. + * + * @param filter - ldap search filter + * @param start - start position for VLV search + * @param pageSize - page size for VLV search + * @param maxResults - max results to be returned in normal search + * @param maxTime - max time for normal search + * @param uriInfo - uri context of request + * @return collection of key request info + * @throws EBaseException + */ + public KeyRequestInfos listRequests(String filter, RequestId start, int pageSize, int maxResults, int maxTime, + UriInfo uriInfo) throws EBaseException { + List <KeyRequestInfo> list = new ArrayList<KeyRequestInfo>(); + List <Link> links = new ArrayList<Link>(); + int totalSize = 0; + int current = 0; + + if (isVLVSearch(filter)) { + IRequestVirtualList vlvlist = queue.getPagedRequestsByFilter(start, false, filter, + pageSize +1 , "requestId"); + totalSize = vlvlist.getSize(); + current = vlvlist.getCurrentIndex(); + + int numRecords = (totalSize > (current + pageSize)) ? pageSize : + totalSize - current; + + for (int i=0; i < numRecords; i++) { + IRequest request = vlvlist.getElementAt(i); + list.add(createKeyRequestInfo(request, uriInfo)); + } + } else { + // The non-vlv requests are indexed, but are not paginated. + // We should think about whether they should be, or if we need to + // limit the number of results returned. + IRequestList requests = queue.listRequestsByFilter(filter, maxResults, maxTime); + + if (requests == null) { + return null; + } + while (requests.hasMoreElements()) { + RequestId rid = requests.nextElement(); + IRequest request = queue.findRequest(rid); + if (request != null) { + list.add(createKeyRequestInfo(request, uriInfo)); + } + } + } + + // builder for vlv links + MultivaluedMap<String, String> params = uriInfo.getQueryParameters(); + UriBuilder builder = uriInfo.getAbsolutePathBuilder(); + if (params.containsKey("requestState")) { + builder.queryParam("requestState", params.getFirst("requestState")); + } + if (params.containsKey("requestType")) { + builder.queryParam("requestType", params.getFirst("requestType")); + } + builder.queryParam("start", "{start}"); + builder.queryParam("pageSize", "{pageSize}"); + + // next link + if (totalSize > current + pageSize) { + int next = current + pageSize + 1; + URI nextUri = builder.clone().build(next,pageSize); + Link nextLink = new Link("next", nextUri.toString(), "application/xml"); + links.add(nextLink); + } + + // previous link + if (current >0) { + int previous = current - pageSize; + URI previousUri = builder.clone().build(previous,pageSize); + Link previousLink = new Link("previous", previousUri.toString(), "application/xml"); + links.add(previousLink); + } + + KeyRequestInfos ret = new KeyRequestInfos(); + ret.setRequests(list); + ret.setLinks(links); + return ret; + } + + /** + * Gets info for a specific request + * @param id + * @return info for specific request + * @throws EBaseException + */ + public KeyRequestInfo getRequest(RequestId id, UriInfo uriInfo) throws EBaseException { + IRequest request = queue.findRequest(id); + if (request == null) { + return null; + } + KeyRequestInfo info = createKeyRequestInfo(request, uriInfo); + return info; + } + /** + * Submits an archival request and processes it. + * @param data + * @return info for the request submitted. + * @throws EBaseException + */ + public KeyRequestInfo submitRequest(ArchivalRequestData data, UriInfo uriInfo) throws EBaseException { + String clientId = data.getClientId(); + String wrappedSecurityData = data.getWrappedPrivateData(); + String dataType = data.getDataType(); + + boolean keyExists = doesKeyExist(clientId, "active", uriInfo); + + if (keyExists == true) { + throw new EBaseException("Can not archive already active existing key!"); + } + + IRequest request = queue.newRequest(IRequest.SECURITY_DATA_ENROLLMENT_REQUEST); + + request.setExtData(REQUEST_ARCHIVE_OPTIONS, wrappedSecurityData); + request.setExtData(IRequest.SECURITY_DATA_CLIENT_ID, clientId); + request.setExtData(IRequest.SECURITY_DATA_TYPE, dataType); + + queue.processRequest(request); + + queue.markAsServiced(request); + + return createKeyRequestInfo(request, uriInfo); + } + /** + * Submits a key recovery request. + * @param data + * @return info on the recovery request created + * @throws EBaseException + */ + public KeyRequestInfo submitRequest(RecoveryRequestData data, UriInfo uriInfo) throws EBaseException { + + // set data using request.setExtData(field, data) + + String wrappedSessionKeyStr = data.getTransWrappedSessionKey(); + String wrappedPassPhraseStr = data.getSessionWrappedPassphrase(); + String nonceDataStr = data.getNonceData(); + + IRequest request = queue.newRequest(IRequest.SECURITY_DATA_RECOVERY_REQUEST); + + KeyId keyId = data.getKeyId(); + + Hashtable<String, Object> requestParams; + requestParams = kra.createVolatileRequest(request.getRequestId()); + + if(requestParams == null) { + throw new EBaseException("Can not create Volatile params in submitRequest!"); + } + + CMS.debug("Create volatile params for recovery request. " + requestParams); + + if (wrappedPassPhraseStr != null) { + requestParams.put(IRequest.SECURITY_DATA_SESS_PASS_PHRASE, wrappedPassPhraseStr); + } + + if (wrappedSessionKeyStr != null) { + requestParams.put(IRequest.SECURITY_DATA_TRANS_SESS_KEY, wrappedSessionKeyStr); + } + + if (nonceDataStr != null) { + requestParams.put(IRequest.SECURITY_DATA_IV_STRING_IN, nonceDataStr); + } + + request.setExtData(ATTR_SERIALNO, keyId.toString()); + + queue.processRequest(request); + + return createKeyRequestInfo(request, uriInfo); + } + + public void approveRequest(RequestId id) throws EBaseException { + IRequest request = queue.findRequest(id); + request.setRequestStatus(RequestStatus.APPROVED); + queue.updateRequest(request); + } + + public void rejectRequest(RequestId id) throws EBaseException { + IRequest request = queue.findRequest(id); + request.setRequestStatus(RequestStatus.CANCELED); + queue.updateRequest(request); + } + + public void cancelRequest(RequestId id) throws EBaseException { + IRequest request = queue.findRequest(id); + request.setRequestStatus(RequestStatus.REJECTED); + queue.updateRequest(request); + } + + public KeyRequestInfo createKeyRequestInfo(IRequest request, UriInfo uriInfo) { + KeyRequestInfo ret = new KeyRequestInfo(); + + ret.setRequestType(request.getRequestType()); + ret.setRequestStatus(request.getRequestStatus().toString()); + + Path keyRequestPath = KeyRequestResource.class.getAnnotation(Path.class); + RequestId rid = request.getRequestId(); + + UriBuilder reqBuilder = uriInfo.getBaseUriBuilder(); + reqBuilder.path(keyRequestPath.value() + "/" + rid); + ret.setRequestURL(reqBuilder.build().toString()); + + Path keyPath = KeyResource.class.getAnnotation(Path.class); + String kid = request.getExtDataInString("keyrecord"); + + UriBuilder keyBuilder = uriInfo.getBaseUriBuilder(); + keyBuilder.path(keyPath.value() + "/" + kid); + ret.setKeyURL(keyBuilder.build().toString()); + + return ret; + } + + private boolean isVLVSearch(String filter) { + for (int i=0; i < vlvFilters.length; i++) { + if (vlvFilters[i].equalsIgnoreCase(filter)) { + return true; + } + } + return false; + } + + //We only care if the key exists or not + private boolean doesKeyExist(String clientId, String keyStatus, UriInfo uriInfo) { + boolean ret = false; + String state = "active"; + + KeyDAO keys = new KeyDAO(); + + KeyDataInfos existingKeys; + String filter = "(&(" + IRequest.SECURITY_DATA_CLIENT_ID + "=" + clientId + ")" + + "(" + IRequest.SECURITY_DATA_STATUS + "=" + state + "))"; + try { + existingKeys = keys.listKeys(filter, 1, 10, uriInfo); + + if(existingKeys != null && existingKeys.getKeyInfos().size() > 0) { + ret = true; + } + } catch (EBaseException e) { + ret= false; + } + + return ret; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfo.java b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfo.java new file mode 100644 index 000000000..f07c302dd --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfo.java @@ -0,0 +1,120 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +package com.netscape.cms.servlet.request.model; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; + +import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.request.RequestId; + +@XmlRootElement(name="SecurityDataRequestInfo") +@XmlAccessorType(XmlAccessType.FIELD) +public class KeyRequestInfo { + + @XmlElement + protected String requestType; + + @XmlElement + protected String requestStatus; + + @XmlElement + protected String requestURL; + + @XmlElement + protected String keyURL; + + public KeyRequestInfo(){ + // required to be here for JAXB (defaults) + } + + /** + * @return the requestType + */ + public String getRequestType() { + return requestType; + } + + /** + * @param requestType the requestType to set + */ + public void setRequestType(String requestType) { + this.requestType = requestType; + } + + /** + * @return the requestStatus + */ + public String getRequestStatus() { + return requestStatus; + } + + /** + * @param requestStatus the requestStatus to set + */ + public void setRequestStatus(String requestStatus) { + this.requestStatus = requestStatus; + } + + /** + * @return the requestURL + */ + public String getRequestURL() { + return requestURL; + } + + /** + * @return the request ID in the requestURL + */ + public RequestId getRequestId() { + String id = requestURL.substring(requestURL.lastIndexOf("/") + 1); + return new RequestId(id); + } + + /** + * @param requestURL the requestURL to set + */ + public void setRequestURL(String requestURL) { + this.requestURL = requestURL; + } + + /** + * @return the keyURL + */ + public String getKeyURL() { + return keyURL; + } + + /** + * @return the key ID in the keyURL + */ + public KeyId getKeyId() { + String id = keyURL.substring(keyURL.lastIndexOf("/") + 1); + return new KeyId(id); + } + + /** + * @param keyURL the keyURL to set + */ + public void setKeyURL(String keyURL) { + this.keyURL = keyURL; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfos.java b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfos.java new file mode 100644 index 000000000..dc1b6a5e4 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/KeyRequestInfos.java @@ -0,0 +1,89 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request.model; + +import java.util.Collection; +import java.util.List; + +import javax.xml.bind.annotation.XmlElementRef; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.netscape.cms.servlet.base.model.Link; + +@XmlRootElement(name = "SecurityDataRequestInfos") +public class KeyRequestInfos { + protected Collection<KeyRequestInfo> requests; + protected List<Link> links; + + /** + * @return the requests + */ + @XmlElementRef + public Collection<KeyRequestInfo> getRequests() { + return requests; + } + + /** + * @param requests the requests to set + */ + public void setRequests(Collection<KeyRequestInfo> requests) { + this.requests = requests; + } + + /** + * @return the links + */ + @XmlElementRef + public List<Link> getLinks() { + return links; + } + + /** + * @param links the links to set + */ + public void setLinks(List<Link> links) { + this.links = links; + } + + @XmlTransient + public String getNext() { + if (links == null) { + return null; + } + for (Link link : links) { + if ("next".equals(link.getRelationship())) { + return link.getHref(); + } + } + return null; + } + + @XmlTransient + public String getPrevious() { + if (links == null) { + return null; + } + for (Link link : links) { + if ("previous".equals(link.getRelationship())) { + return link.getHref(); + } + } + return null; + } +} diff --git a/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java b/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java new file mode 100644 index 000000000..80ec6d127 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/request/model/RecoveryRequestData.java @@ -0,0 +1,155 @@ +// --- 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) 2011 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- + +/** + * + */ +package com.netscape.cms.servlet.request.model; + +import javax.ws.rs.core.MultivaluedMap; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import com.netscape.certsrv.dbs.keydb.KeyId; +import com.netscape.certsrv.dbs.keydb.KeyIdAdapter; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.RequestIdAdapter; + +/** + * @author alee + * + */ +@XmlRootElement(name="SecurityDataRecoveryRequest") +@XmlAccessorType(XmlAccessType.FIELD) +public class RecoveryRequestData { + + private static final String KEY_ID = "keyId"; + private static final String REQUEST_ID = "requestId"; + private static final String TRANS_WRAPPED_SESSION_KEY = "transWrappedSessionKey"; + private static final String SESSION_WRAPPED_PASSPHRASE = "sessionWrappedPassphrase"; + private static final String NONCE_DATA = "nonceData"; + + @XmlElement + @XmlJavaTypeAdapter(KeyIdAdapter.class) + protected KeyId keyId; + + @XmlElement + @XmlJavaTypeAdapter(RequestIdAdapter.class) + protected RequestId requestId; + + @XmlElement + protected String transWrappedSessionKey; + + @XmlElement + protected String sessionWrappedPassphrase; + + @XmlElement + protected String nonceData; + + public RecoveryRequestData() { + // required for JAXB (defaults) + } + + public RecoveryRequestData(MultivaluedMap<String, String> form) { + if (form.containsKey(KEY_ID)) { + keyId = new KeyId(form.getFirst(KEY_ID)); + } + if (form.containsKey(REQUEST_ID)) { + requestId = new RequestId(form.getFirst(REQUEST_ID)); + } + transWrappedSessionKey = form.getFirst(TRANS_WRAPPED_SESSION_KEY); + sessionWrappedPassphrase = form.getFirst(SESSION_WRAPPED_PASSPHRASE); + nonceData = form.getFirst(NONCE_DATA); + } + + /** + * @return the keyId + */ + public KeyId getKeyId() { + return keyId; + } + + /** + * @param keyId the keyId to set + */ + public void setKeyId(KeyId keyId) { + this.keyId = keyId; + } + + /** + * @return the requestId + */ + public RequestId getRequestId() { + return requestId; + } + + /** + * @param requestId the requestId to set + */ + public void setRequestId(RequestId requestId) { + this.requestId = requestId; + } + + /** + * @return the transWrappedSessionKey + */ + public String getTransWrappedSessionKey() { + return transWrappedSessionKey; + } + + /** + * @param transWrappedSessionKey the transWrappedSessionKey to set + */ + public void setTransWrappedSessionKey(String transWrappedSessionKey) { + this.transWrappedSessionKey = transWrappedSessionKey; + } + + /** + * @return the sessionWrappedPassphrase + */ + public String getSessionWrappedPassphrase() { + return sessionWrappedPassphrase; + } + + /** + * @param sessionWrappedPassphrase the sessionWrappedPassphrase to set + */ + public void setSessionWrappedPassphrase(String sessionWrappedPassphrase) { + this.sessionWrappedPassphrase = sessionWrappedPassphrase; + } + + /** + * @return nonceData + */ + + public String getNonceData() { + return nonceData; + } + + /** + * @param nonceData the nonceData to set + */ + + public void setNonceData(String nonceData) { + this.nonceData = nonceData; + } + +} diff --git a/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java b/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java new file mode 100644 index 000000000..c96a30a85 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java @@ -0,0 +1,1340 @@ +// --- 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.tks; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.util.StringTokenizer; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.KeyWrapAlgorithm; +import org.mozilla.jss.crypto.KeyWrapper; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.pkcs11.PK11SymKey; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IPrettyPrintFormat; +import com.netscape.certsrv.base.SessionContext; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.tks.ITKSAuthority; +import com.netscape.cms.servlet.base.CMSServlet; +import com.netscape.cms.servlet.common.CMSRequest; +import com.netscape.symkey.SessionKey; + +/** + * A class representings an administration servlet for Token Key + * Service Authority. This servlet is responsible to serve + * tks administrative operation such as configuration + * parameter updates. + * + * @version $Revision$, $Date$ + */ +public class TokenServlet extends CMSServlet { + /** + * + */ + private static final long serialVersionUID = 8687436109695172791L; + protected static final String PROP_ENABLED = "enabled"; + protected static final String TRANSPORT_KEY_NAME = "sharedSecret"; + private final static String INFO = "TokenServlet"; + public static int ERROR = 1; + private ITKSAuthority mTKS = null; + private String mSelectedToken = null; + private String mNewSelectedToken = null; + String mKeyNickName = null; + String mNewKeyNickName = null; + private final static String LOGGING_SIGNED_AUDIT_CONFIG_DRM = + "LOGGING_SIGNED_AUDIT_CONFIG_DRM_3"; + IPrettyPrintFormat pp = CMS.getPrettyPrintFormat(":"); + + private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST = + "LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_3"; + + private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS_8"; + + private final static String LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE_9"; + + private final static String LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST = + "LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_5"; + + private final static String LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS_6"; + + private final static String LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE_7"; + + private final static String LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST = + "LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_4"; + + private final static String LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS_7"; + + private final static String LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE_8"; + + private final static String LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST = + "LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_2"; + + private final static String LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS = + "LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS_3"; + + private final static String LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE = + "LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE_4"; + + /** + * Constructs tks servlet. + */ + public TokenServlet() { + super(); + + } + + public static String trim(String a) { + StringBuffer newa = new StringBuffer(); + StringTokenizer tokens = new StringTokenizer(a, "\n"); + while (tokens.hasMoreTokens()) { + newa.append(tokens.nextToken()); + } + return newa.toString(); + } + + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + /** + * Returns serlvet information. + * + * @return name of this servlet + */ + public String getServletInfo() { + return INFO; + } + + /** + * Process the HTTP request. + * + * @param s The URL to decode. + */ + protected String URLdecode(String s) { + if (s == null) + return null; + ByteArrayOutputStream out = new ByteArrayOutputStream(s.length()); + + for (int i = 0; i < s.length(); i++) { + int c = (int) s.charAt(i); + + if (c == '+') { + out.write(' '); + } else if (c == '%') { + int c1 = Character.digit(s.charAt(++i), 16); + int c2 = Character.digit(s.charAt(++i), 16); + + out.write((char) (c1 * 16 + c2)); + } else { + out.write(c); + } + } // end for + return out.toString(); + } + + private void setDefaultSlotAndKeyName(HttpServletRequest req) { + try { + + String keySet = req.getParameter("keySet"); + if (keySet == null || keySet.equals("")) { + keySet = "defKeySet"; + } + CMS.debug("keySet selected: " + keySet); + + mNewSelectedToken = null; + + mSelectedToken = CMS.getConfigStore().getString("tks.defaultSlot"); + String masterKeyPrefix = CMS.getConfigStore().getString("tks.master_key_prefix", null); + String temp = req.getParameter("KeyInfo"); //#xx#xx + String keyInfoMap = "tks." + keySet + ".mk_mappings." + temp; + String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null); + if (mappingValue != null) { + StringTokenizer st = new StringTokenizer(mappingValue, ":"); + int tokenNumber = 0; + while (st.hasMoreTokens()) { + + String currentToken = st.nextToken(); + if (tokenNumber == 0) + mSelectedToken = currentToken; + else if (tokenNumber == 1) + mKeyNickName = currentToken; + tokenNumber++; + + } + } + if (req.getParameter("newKeyInfo") != null) // for diversification + { + temp = req.getParameter("newKeyInfo"); //#xx#xx + String newKeyInfoMap = "tks." + keySet + ".mk_mappings." + temp; + String newMappingValue = CMS.getConfigStore().getString(newKeyInfoMap, null); + if (newMappingValue != null) { + StringTokenizer st = new StringTokenizer(newMappingValue, ":"); + int tokenNumber = 0; + while (st.hasMoreTokens()) { + String currentToken = st.nextToken(); + if (tokenNumber == 0) + mNewSelectedToken = currentToken; + else if (tokenNumber == 1) + mNewKeyNickName = currentToken; + tokenNumber++; + + } + } + } + + SessionKey.SetDefaultPrefix(masterKeyPrefix); + + } catch (Exception e) { + e.printStackTrace(); + CMS.debug("Exception in TokenServlet::setDefaultSlotAndKeyName"); + } + + } + + private void processComputeSessionKey(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + byte[] card_challenge, host_challenge, keyInfo, xCUID, CUID, session_key; + byte[] card_crypto, host_cryptogram, input_card_crypto; + byte[] xcard_challenge, xhost_challenge; + byte[] enc_session_key, xkeyInfo; + String auditMessage = null; + String errorMsg = ""; + String badParams = ""; + String transportKeyName = ""; + + String rCUID = req.getParameter("CUID"); + String keySet = req.getParameter("keySet"); + if (keySet == null || keySet.equals("")) { + keySet = "defKeySet"; + } + CMS.debug("keySet selected: " + keySet); + + boolean serversideKeygen = false; + byte[] drm_trans_wrapped_desKey = null; + PK11SymKey desKey = null; + // PK11SymKey kek_session_key; + PK11SymKey kek_key; + + IConfigStore sconfig = CMS.getConfigStore(); + boolean isCryptoValidate = true; + boolean missingParam = false; + session_key = null; + card_crypto = null; + host_cryptogram = null; + enc_session_key = null; + // kek_session_key = null; + + SessionContext sContext = SessionContext.getContext(); + + String agentId = ""; + if (sContext != null) { + agentId = + (String) sContext.get(SessionContext.USER_ID); + } + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST, + rCUID, + ILogger.SUCCESS, + agentId); + + audit(auditMessage); + + String kek_wrapped_desKeyString = null; + String keycheck_s = null; + + CMS.debug("processComputeSessionKey:"); + String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true"); + if (!useSoftToken_s.equalsIgnoreCase("true")) + useSoftToken_s = "false"; + + String rServersideKeygen = (String) req.getParameter("serversideKeygen"); + if (rServersideKeygen.equals("true")) { + CMS.debug("TokenServlet: serversideKeygen requested"); + serversideKeygen = true; + } else { + CMS.debug("TokenServlet: serversideKeygen not requested"); + } + + try { + isCryptoValidate = sconfig.getBoolean("cardcryptogram.validate.enable", true); + } catch (EBaseException eee) { + } + + try { + transportKeyName = sconfig.getString("tks.tksSharedSymKeyName", TRANSPORT_KEY_NAME); + } catch (EBaseException e) { + } + + CMS.debug("TokenServlet: ComputeSessionKey(): tksSharedSymKeyName: " + transportKeyName); + + String rcard_challenge = req.getParameter("card_challenge"); + String rhost_challenge = req.getParameter("host_challenge"); + String rKeyInfo = req.getParameter("KeyInfo"); + String rcard_cryptogram = req.getParameter("card_cryptogram"); + if ((rCUID == null) || (rCUID.equals(""))) { + CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: CUID"); + badParams += " CUID,"; + missingParam = true; + } + + if ((rcard_challenge == null) || (rcard_challenge.equals(""))) { + badParams += " card_challenge,"; + CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: card challenge"); + missingParam = true; + } + + if ((rhost_challenge == null) || (rhost_challenge.equals(""))) { + badParams += " host_challenge,"; + CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: host challenge"); + missingParam = true; + } + + if ((rKeyInfo == null) || (rKeyInfo.equals(""))) { + badParams += " KeyInfo,"; + CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: key info"); + missingParam = true; + } + + String selectedToken = null; + String keyNickName = null; + boolean sameCardCrypto = true; + + if (!missingParam) { + + xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); + if (xCUID == null || xCUID.length != 10) { + badParams += " CUID length,"; + CMS.debug("TokenServlet: Invalid CUID length"); + missingParam = true; + } + xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo); + if (xkeyInfo == null || xkeyInfo.length != 2) { + badParams += " KeyInfo length,"; + CMS.debug("TokenServlet: Invalid key info length."); + missingParam = true; + } + xcard_challenge = + com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_challenge); + if (xcard_challenge == null || xcard_challenge.length != 8) { + badParams += " card_challenge length,"; + CMS.debug("TokenServlet: Invalid card challenge length."); + missingParam = true; + } + + xhost_challenge = com.netscape.cmsutil.util.Utils.SpecialDecode(rhost_challenge); + if (xhost_challenge == null || xhost_challenge.length != 8) { + badParams += " host_challenge length,"; + CMS.debug("TokenServlet: Invalid host challenge length"); + missingParam = true; + } + + } + + CUID = null; + if (!missingParam) { + card_challenge = + com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_challenge); + + host_challenge = com.netscape.cmsutil.util.Utils.SpecialDecode(rhost_challenge); + keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo); + + CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); + + String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo; //#xx#xx + String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null); + if (mappingValue == null) { + selectedToken = + CMS.getConfigStore().getString("tks.defaultSlot", "internal"); + keyNickName = rKeyInfo; + } else { + StringTokenizer st = new StringTokenizer(mappingValue, ":"); + if (st.hasMoreTokens()) + selectedToken = st.nextToken(); + if (st.hasMoreTokens()) + keyNickName = st.nextToken(); + } + + if (selectedToken != null && keyNickName != null) { + + try { + + byte macKeyArray[] = + com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + + keySet + ".mac_key")); + CMS.debug("TokenServlet about to try ComputeSessionKey selectedToken=" + + selectedToken + " keyNickName=" + keyNickName); + session_key = SessionKey.ComputeSessionKey( + selectedToken, keyNickName, card_challenge, + host_challenge, keyInfo, CUID, macKeyArray, useSoftToken_s, keySet, transportKeyName); + + if (session_key == null) { + CMS.debug("TokenServlet:Tried ComputeSessionKey, got NULL "); + throw new Exception("Can't compute session key!"); + + } + + byte encKeyArray[] = + com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + + keySet + ".auth_key")); + enc_session_key = SessionKey.ComputeEncSessionKey( + selectedToken, keyNickName, card_challenge, + host_challenge, keyInfo, CUID, encKeyArray, useSoftToken_s, keySet); + + if (enc_session_key == null) { + CMS.debug("TokenServlet:Tried ComputeEncSessionKey, got NULL "); + throw new Exception("Can't compute enc session key!"); + + } + + if (serversideKeygen == true) { + + /** + * 0. generate des key + * 1. encrypt des key with kek key + * 2. encrypt des key with DRM transport key + * These two wrapped items are to be sent back to + * TPS. 2nd item is to DRM + **/ + CMS.debug("TokenServlet: calling ComputeKekKey"); + + byte kekKeyArray[] = + com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + + keySet + ".kek_key")); + + kek_key = SessionKey.ComputeKekKey( + selectedToken, keyNickName, card_challenge, + host_challenge, keyInfo, CUID, kekKeyArray, useSoftToken_s, keySet); + + CMS.debug("TokenServlet: called ComputeKekKey"); + + if (kek_key == null) { + CMS.debug("TokenServlet:Tried ComputeKekKey, got NULL "); + throw new Exception("Can't compute kek key!"); + + } + // now use kek key to wrap kek session key.. + CMS.debug("computeSessionKey:kek key len =" + + kek_key.getLength()); + + // (1) generate DES key + /* applet does not support DES3 + org.mozilla.jss.crypto.KeyGenerator kg = + internalToken.getKeyGenerator(KeyGenAlgorithm.DES3); + desKey = kg.generate();*/ + + /* + * XXX GenerateSymkey firt generates a 16 byte DES2 key. + * It then pads it into a 24 byte key with last + * 8 bytes copied from the 1st 8 bytes. Effectively + * making it a 24 byte DES2 key. We need this for + * wrapping private keys on DRM. + */ + /*generate it on whichever token the master key is at*/ + if (useSoftToken_s.equals("true")) { + CMS.debug("TokenServlet: key encryption key generated on internal"); + //cfu audit here? sym key gen + desKey = SessionKey.GenerateSymkey("internal"); + //cfu audit here? sym key gen done + } else { + CMS.debug("TokenServlet: key encryption key generated on " + selectedToken); + desKey = SessionKey.GenerateSymkey(selectedToken); + } + if (desKey != null) + CMS.debug("TokenServlet: key encryption key generated for " + rCUID); + else { + CMS.debug("TokenServlet: key encryption key generation failed for " + rCUID); + throw new Exception("can't generate key encryption key"); + } + + /* + * XXX ECBencrypt actually takes the 24 byte DES2 key + * and discard the last 8 bytes before it encrypts. + * This is done so that the applet can digest it + */ + byte[] encDesKey = + SessionKey.ECBencrypt(kek_key, + desKey); + /* + CMS.debug("computeSessionKey:encrypted desKey size = "+encDesKey.length); + CMS.debug(encDesKey); + */ + + kek_wrapped_desKeyString = + com.netscape.cmsutil.util.Utils.SpecialEncode(encDesKey); + + // get keycheck + byte[] keycheck = + SessionKey.ComputeKeyCheck(desKey); + /* + CMS.debug("computeSessionKey:keycheck size = "+keycheck.length); + CMS.debug(keycheck); + */ + keycheck_s = + com.netscape.cmsutil.util.Utils.SpecialEncode(keycheck); + + //XXX use DRM transport cert to wrap desKey + String drmTransNickname = CMS.getConfigStore().getString("tks.drm_transport_cert_nickname", ""); + + if ((drmTransNickname == null) || (drmTransNickname == "")) { + CMS.debug("TokenServlet:did not find DRM transport certificate nickname"); + throw new Exception("can't find DRM transport certificate nickname"); + } else { + CMS.debug("TokenServlet:drmtransport_cert_nickname=" + drmTransNickname); + } + + X509Certificate drmTransCert = null; + drmTransCert = CryptoManager.getInstance().findCertByNickname(drmTransNickname); + // wrap kek session key with DRM transport public key + CryptoToken token = null; + if (useSoftToken_s.equals("true")) { + //token = CryptoManager.getInstance().getTokenByName(selectedToken); + token = CryptoManager.getInstance().getInternalCryptoToken(); + } else { + token = CryptoManager.getInstance().getTokenByName(selectedToken); + } + PublicKey pubKey = drmTransCert.getPublicKey(); + String pubKeyAlgo = pubKey.getAlgorithm(); + CMS.debug("Transport Cert Key Algorithm: " + pubKeyAlgo); + KeyWrapper keyWrapper = null; + //For wrapping symmetric keys don't need IV, use ECB + if (pubKeyAlgo.equals("EC")) { + keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.AES_ECB); + keyWrapper.initWrap(pubKey, null); + } else { + keyWrapper = token.getKeyWrapper(KeyWrapAlgorithm.RSA); + keyWrapper.initWrap(pubKey, null); + } + CMS.debug("desKey token " + desKey.getOwningToken().getName() + " token: " + token.getName()); + drm_trans_wrapped_desKey = keyWrapper.wrap(desKey); + CMS.debug("computeSessionKey:desKey wrapped with drm transportation key."); + + } // if (serversideKeygen == true) + + byte authKeyArray[] = + com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + + keySet + ".auth_key")); + host_cryptogram = SessionKey.ComputeCryptogram( + selectedToken, keyNickName, card_challenge, + host_challenge, keyInfo, CUID, 0, authKeyArray, useSoftToken_s, keySet); + + if (host_cryptogram == null) { + CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL "); + throw new Exception("Can't compute host cryptogram!"); + + } + card_crypto = SessionKey.ComputeCryptogram( + selectedToken, keyNickName, card_challenge, + host_challenge, keyInfo, CUID, 1, authKeyArray, useSoftToken_s, keySet); + + if (card_crypto == null) { + CMS.debug("TokenServlet:Tried ComputeCryptogram, got NULL "); + throw new Exception("Can't compute card cryptogram!"); + + } + + if (isCryptoValidate) { + if (rcard_cryptogram == null) { + CMS.debug("TokenServlet: ComputeCryptogram(): missing card cryptogram"); + throw new Exception("Missing card cryptogram"); + } + input_card_crypto = + com.netscape.cmsutil.util.Utils.SpecialDecode(rcard_cryptogram); + if (card_crypto.length == input_card_crypto.length) { + for (int i = 0; i < card_crypto.length; i++) { + if (card_crypto[i] != input_card_crypto[i]) { + sameCardCrypto = false; + break; + } + } + } else { + // different length; must be different + sameCardCrypto = false; + } + } + + CMS.getLogger().log(ILogger.EV_AUDIT, + ILogger.S_TKS, + ILogger.LL_INFO, "processComputeSessionKey for CUID=" + + trim(pp.toHexString(CUID))); + } catch (Exception e) { + CMS.debug(e); + CMS.debug("TokenServlet Computing Session Key: " + e.toString()); + if (isCryptoValidate) + sameCardCrypto = false; + } + } + } // ! missingParam + + String value = ""; + + resp.setContentType("text/html"); + + String outputString = ""; + String encSessionKeyString = ""; + String drm_trans_wrapped_desKeyString = ""; + String cryptogram = ""; + String status = "0"; + if (session_key != null && session_key.length > 0) { + outputString = + com.netscape.cmsutil.util.Utils.SpecialEncode(session_key); + } else { + + status = "1"; + } + + if (enc_session_key != null && enc_session_key.length > 0) { + encSessionKeyString = + com.netscape.cmsutil.util.Utils.SpecialEncode(enc_session_key); + } else { + status = "1"; + } + + if (serversideKeygen == true) { + if (drm_trans_wrapped_desKey != null && drm_trans_wrapped_desKey.length > 0) + drm_trans_wrapped_desKeyString = + com.netscape.cmsutil.util.Utils.SpecialEncode(drm_trans_wrapped_desKey); + else { + status = "1"; + } + } + + if (host_cryptogram != null && host_cryptogram.length > 0) { + cryptogram = + com.netscape.cmsutil.util.Utils.SpecialEncode(host_cryptogram); + } else { + status = "2"; + } + + if (selectedToken == null || keyNickName == null) { + status = "4"; + } + + if (!sameCardCrypto) { + status = "3"; + } + + if (missingParam) { + status = "3"; + } + + if (!status.equals("0")) { + + if (status.equals("1")) { + errorMsg = "Problem generating session key info."; + } + + if (status.equals("2")) { + errorMsg = "Problem creating host_cryptogram."; + } + + if (status.equals("4")) { + errorMsg = "Problem obtaining token information."; + } + + if (status.equals("3")) { + if (badParams.endsWith(",")) { + badParams = badParams.substring(0, badParams.length() - 1); + } + errorMsg = "Missing input parameters :" + badParams; + } + + value = "status=" + status; + } else { + if (serversideKeygen == true) { + StringBuffer sb = new StringBuffer(); + sb.append("status=0&"); + sb.append("sessionKey="); + sb.append(outputString); + sb.append("&hostCryptogram="); + sb.append(cryptogram); + sb.append("&encSessionKey="); + sb.append(encSessionKeyString); + sb.append("&kek_wrapped_desKey="); + sb.append(kek_wrapped_desKeyString); + sb.append("&keycheck="); + sb.append(keycheck_s); + sb.append("&drm_trans_wrapped_desKey="); + sb.append(drm_trans_wrapped_desKeyString); + value = sb.toString(); + } else { + StringBuffer sb = new StringBuffer(); + sb.append("status=0&"); + sb.append("sessionKey="); + sb.append(outputString); + sb.append("&hostCryptogram="); + sb.append(cryptogram); + sb.append("&encSessionKey="); + sb.append(encSessionKeyString); + value = sb.toString(); + } + + } + CMS.debug("TokenServlet:outputString.encode " + value); + + try { + resp.setContentLength(value.length()); + CMS.debug("TokenServlet:outputString.length " + value.length()); + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (IOException e) { + CMS.debug("TokenServlet: " + e.toString()); + } + + if (status.equals("0")) { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_SUCCESS, + rCUID, + ILogger.SUCCESS, + status, + agentId, + isCryptoValidate ? "true" : "false", + serversideKeygen ? "true" : "false", + selectedToken, + keyNickName); + + } else { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_COMPUTE_SESSION_KEY_REQUEST_PROCESSED_FAILURE, + rCUID, + ILogger.FAILURE, + status, + agentId, + isCryptoValidate ? "true" : "false", + serversideKeygen ? "true" : "false", + selectedToken, + keyNickName, + errorMsg); + } + + audit(auditMessage); + } + + private void processDiversifyKey(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + byte[] KeySetData, CUID, xCUID; + byte[] xkeyInfo, xnewkeyInfo; + boolean missingParam = false; + String errorMsg = ""; + String badParams = ""; + + IConfigStore sconfig = CMS.getConfigStore(); + String rnewKeyInfo = req.getParameter("newKeyInfo"); + String newMasterKeyName = req.getParameter("newKeyInfo"); + String oldMasterKeyName = req.getParameter("KeyInfo"); + String rCUID = req.getParameter("CUID"); + String auditMessage = ""; + + String keySet = req.getParameter("keySet"); + if (keySet == null || keySet.equals("")) { + keySet = "defKeySet"; + } + CMS.debug("keySet selected: " + keySet); + + SessionContext sContext = SessionContext.getContext(); + + String agentId = ""; + if (sContext != null) { + agentId = + (String) sContext.get(SessionContext.USER_ID); + } + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST, + rCUID, + ILogger.SUCCESS, + agentId, + oldMasterKeyName, + newMasterKeyName); + + audit(auditMessage); + + if ((rCUID == null) || (rCUID.equals(""))) { + badParams += " CUID,"; + CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: CUID"); + missingParam = true; + } + if ((rnewKeyInfo == null) || (rnewKeyInfo.equals(""))) { + badParams += " newKeyInfo,"; + CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: newKeyInfo"); + missingParam = true; + } + if ((oldMasterKeyName == null) || (oldMasterKeyName.equals(""))) { + badParams += " KeyInfo,"; + CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: KeyInfo"); + missingParam = true; + } + + if (!missingParam) { + xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(oldMasterKeyName); + if (xkeyInfo == null || xkeyInfo.length != 2) { + badParams += " KeyInfo length,"; + CMS.debug("TokenServlet: Invalid key info length"); + missingParam = true; + } + xnewkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(newMasterKeyName); + if (xnewkeyInfo == null || xnewkeyInfo.length != 2) { + badParams += " NewKeyInfo length,"; + CMS.debug("TokenServlet: Invalid new key info length"); + missingParam = true; + } + } + String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true"); + if (!useSoftToken_s.equalsIgnoreCase("true")) + useSoftToken_s = "false"; + + KeySetData = null; + if (!missingParam) { + xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); + if (xCUID == null || xCUID.length != 10) { + badParams += " CUID length,"; + CMS.debug("TokenServlet: Invalid CUID length"); + missingParam = true; + } + } + if (!missingParam) { + CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); + + if (mKeyNickName != null) + oldMasterKeyName = mKeyNickName; + if (mNewKeyNickName != null) + newMasterKeyName = mNewKeyNickName; + + String oldKeyInfoMap = "tks." + keySet + ".mk_mappings." + req.getParameter("KeyInfo"); //#xx#xx + String oldMappingValue = CMS.getConfigStore().getString(oldKeyInfoMap, null); + String oldSelectedToken = null; + String oldKeyNickName = null; + if (oldMappingValue == null) { + oldSelectedToken = CMS.getConfigStore().getString("tks.defaultSlot", "internal"); + oldKeyNickName = req.getParameter("KeyInfo"); + } else { + StringTokenizer st = new StringTokenizer(oldMappingValue, ":"); + oldSelectedToken = st.nextToken(); + oldKeyNickName = st.nextToken(); + } + + String newKeyInfoMap = "tks.mk_mappings." + rnewKeyInfo; //#xx#xx + String newMappingValue = CMS.getConfigStore().getString(newKeyInfoMap, null); + String newSelectedToken = null; + String newKeyNickName = null; + if (newMappingValue == null) { + newSelectedToken = CMS.getConfigStore().getString("tks.defaultSlot", "internal"); + newKeyNickName = rnewKeyInfo; + } else { + StringTokenizer st = new StringTokenizer(newMappingValue, ":"); + newSelectedToken = st.nextToken(); + newKeyNickName = st.nextToken(); + } + + CMS.debug("process DiversifyKey for oldSelectedToke=" + + oldSelectedToken + " newSelectedToken=" + newSelectedToken + + " oldKeyNickName=" + oldKeyNickName + " newKeyNickName=" + + newKeyNickName); + + byte kekKeyArray[] = + com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key")); + KeySetData = SessionKey.DiversifyKey(oldSelectedToken, + newSelectedToken, oldKeyNickName, + newKeyNickName, rnewKeyInfo, CUID, kekKeyArray, useSoftToken_s, keySet); + + if (KeySetData == null || KeySetData.length <= 1) { + CMS.getLogger().log(ILogger.EV_AUDIT, + ILogger.S_TKS, + ILogger.LL_INFO, "process DiversifyKey: Missing MasterKey in Slot"); + } + + CMS.getLogger().log(ILogger.EV_AUDIT, + ILogger.S_TKS, + ILogger.LL_INFO, "process DiversifyKey for CUID =" + trim(pp.toHexString(CUID)) + + ";from oldMasterKeyName=" + oldSelectedToken + ":" + oldKeyNickName + + ";to newMasterKeyName=" + newSelectedToken + ":" + newKeyNickName); + + resp.setContentType("text/html"); + } // ! missingParam + + //CMS.debug("TokenServlet:processDiversifyKey " +outputString); + //String value="keySetData=%00" if the KeySetData=byte[0]=0; + + String value = ""; + String status = "0"; + + if (KeySetData != null && KeySetData.length > 1) { + value = "status=0&" + "keySetData=" + + com.netscape.cmsutil.util.Utils.SpecialEncode(KeySetData); + CMS.debug("TokenServlet:process DiversifyKey.encode " + value); + } else if (missingParam) { + status = "3"; + if (badParams.endsWith(",")) { + badParams = badParams.substring(0, badParams.length() - 1); + } + errorMsg = "Missing input parameters: " + badParams; + value = "status=" + status; + } else { + errorMsg = "Problem diversifying key data."; + status = "1"; + value = "status=" + status; + } + + resp.setContentLength(value.length()); + CMS.debug("TokenServlet:outputString.length " + value.length()); + + try { + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (Exception e) { + CMS.debug("TokenServlet:process DiversifyKey: " + e.toString()); + } + + if (status.equals("0")) { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_SUCCESS, + rCUID, + ILogger.SUCCESS, + status, + agentId, + oldMasterKeyName, + newMasterKeyName); + + } else { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_DIVERSIFY_KEY_REQUEST_PROCESSED_FAILURE, + rCUID, + ILogger.FAILURE, + status, + agentId, + oldMasterKeyName, + newMasterKeyName, + errorMsg); + } + + audit(auditMessage); + } + + private void processEncryptData(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + byte[] keyInfo, CUID, xCUID, encryptedData, xkeyInfo; + boolean missingParam = false; + byte[] data = null; + boolean isRandom = true; // randomly generate the data to be encrypted + + String errorMsg = ""; + String badParams = ""; + IConfigStore sconfig = CMS.getConfigStore(); + encryptedData = null; + String rdata = req.getParameter("data"); + String rKeyInfo = req.getParameter("KeyInfo"); + String rCUID = req.getParameter("CUID"); + String keySet = req.getParameter("keySet"); + if (keySet == null || keySet.equals("")) { + keySet = "defKeySet"; + } + + SessionContext sContext = SessionContext.getContext(); + + String agentId = ""; + if (sContext != null) { + agentId = + (String) sContext.get(SessionContext.USER_ID); + } + + CMS.debug("keySet selected: " + keySet); + + String s_isRandom = sconfig.getString("tks.EncryptData.isRandom", "true"); + if (s_isRandom.equalsIgnoreCase("false")) { + CMS.debug("TokenServlet: processEncryptData(): Random number not to be generated"); + isRandom = false; + } else { + CMS.debug("TokenServlet: processEncryptData(): Random number generation required"); + isRandom = true; + } + + String auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST, + rCUID, + ILogger.SUCCESS, + agentId, + s_isRandom); + + audit(auditMessage); + + if (isRandom) { + if ((rdata == null) || (rdata.equals(""))) { + CMS.debug("TokenServlet: processEncryptData(): no data in request. Generating random number as data"); + } else { + CMS.debug("TokenServlet: processEncryptData(): contain data in request, however, random generation on TKS is required. Generating..."); + } + try { + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + data = new byte[16]; + random.nextBytes(data); + } catch (Exception e) { + CMS.debug("TokenServlet: processEncryptData():" + e.toString()); + badParams += " Random Number,"; + missingParam = true; + } + } else if ((!isRandom) && (((rdata == null) || (rdata.equals(""))))) { + CMS.debug("TokenServlet: processEncryptData(): missing request parameter: data."); + badParams += " data,"; + missingParam = true; + } + + if ((rCUID == null) || (rCUID.equals(""))) { + badParams += " CUID,"; + CMS.debug("TokenServlet: processEncryptData(): missing request parameter: CUID"); + missingParam = true; + } + + if ((rKeyInfo == null) || (rKeyInfo.equals(""))) { + badParams += " KeyInfo,"; + CMS.debug("TokenServlet: processEncryptData(): missing request parameter: key info"); + missingParam = true; + } + + if (!missingParam) { + xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); + if (xCUID == null || xCUID.length != 10) { + badParams += " CUID length,"; + CMS.debug("TokenServlet: Invalid CUID length"); + missingParam = true; + } + xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo); + if (xkeyInfo == null || xkeyInfo.length != 2) { + badParams += " KeyInfo length,"; + CMS.debug("TokenServlet: Invalid key info length"); + missingParam = true; + } + } + + String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken", "true"); + if (!useSoftToken_s.equalsIgnoreCase("true")) + useSoftToken_s = "false"; + + String selectedToken = null; + String keyNickName = null; + if (!missingParam) { + if (!isRandom) + data = com.netscape.cmsutil.util.Utils.SpecialDecode(rdata); + keyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo); + CUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); + + String keyInfoMap = "tks." + keySet + ".mk_mappings." + rKeyInfo; + String mappingValue = CMS.getConfigStore().getString(keyInfoMap, null); + if (mappingValue == null) { + selectedToken = CMS.getConfigStore().getString("tks.defaultSlot", "internal"); + keyNickName = rKeyInfo; + } else { + StringTokenizer st = new StringTokenizer(mappingValue, ":"); + selectedToken = st.nextToken(); + keyNickName = st.nextToken(); + } + + byte kekKeyArray[] = + com.netscape.cmsutil.util.Utils.SpecialDecode(sconfig.getString("tks." + keySet + ".kek_key")); + encryptedData = SessionKey.EncryptData( + selectedToken, keyNickName, data, keyInfo, CUID, kekKeyArray, useSoftToken_s, keySet); + + CMS.getLogger().log(ILogger.EV_AUDIT, + ILogger.S_TKS, + ILogger.LL_INFO, "process EncryptData for CUID =" + trim(pp.toHexString(CUID))); + } // !missingParam + + resp.setContentType("text/html"); + + String value = ""; + String status = "0"; + if (encryptedData != null && encryptedData.length > 0) { + // sending both the pre-encrypted and encrypted data back + value = "status=0&" + "data=" + + com.netscape.cmsutil.util.Utils.SpecialEncode(data) + + "&encryptedData=" + + com.netscape.cmsutil.util.Utils.SpecialEncode(encryptedData); + } else if (missingParam) { + if (badParams.endsWith(",")) { + badParams = badParams.substring(0, badParams.length() - 1); + } + errorMsg = "Missing input parameters: " + badParams; + status = "3"; + value = "status=" + status; + } else { + errorMsg = "Problem encrypting data."; + status = "1"; + value = "status=" + status; + } + + CMS.debug("TokenServlet:process EncryptData.encode " + value); + + try { + resp.setContentLength(value.length()); + CMS.debug("TokenServlet:outputString.lenght " + value.length()); + + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (Exception e) { + CMS.debug("TokenServlet: " + e.toString()); + } + + if (status.equals("0")) { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_SUCCESS, + rCUID, + ILogger.SUCCESS, + status, + agentId, + s_isRandom, + selectedToken, + keyNickName); + + } else { + + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_ENCRYPT_DATA_REQUEST_PROCESSED_FAILURE, + rCUID, + ILogger.FAILURE, + status, + agentId, + s_isRandom, + selectedToken, + keyNickName, + errorMsg); + } + + audit(auditMessage); + } + + /* + * For EncryptData: + * data=value1 + * CUID=value2 // missing from RA + * versionID=value3 // missing from RA + * + * For ComputeSession: + * card_challenge=value1 + * host_challenge=value2 + + * For DiversifyKey: + * new_master_key_index + * master_key_index + */ + + private void processComputeRandomData(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + + byte[] randomData = null; + String status = "0"; + String errorMsg = ""; + String badParams = ""; + boolean missingParam = false; + int dataSize = 0; + + CMS.debug("TokenServlet::processComputeRandomData"); + + SessionContext sContext = SessionContext.getContext(); + + String agentId = ""; + if (sContext != null) { + agentId = + (String) sContext.get(SessionContext.USER_ID); + } + + String sDataSize = req.getParameter("dataNumBytes"); + + if (sDataSize == null || sDataSize.equals("")) { + CMS.debug("TokenServlet::processComputeRandomData missing param dataNumBytes"); + badParams += " Random Data size, "; + missingParam = true; + status = "1"; + } else { + try { + dataSize = Integer.parseInt(sDataSize.trim()); + } catch (NumberFormatException nfe) { + CMS.debug("TokenServlet::processComputeRandomData invalid data size input!"); + badParams += " Random Data size, "; + missingParam = true; + status = "1"; + } + + } + + CMS.debug("TokenServlet::processComputeRandomData data size requested: " + dataSize); + + String auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST, + ILogger.SUCCESS, + agentId); + + audit(auditMessage); + + if (!missingParam) { + try { + SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); + randomData = new byte[dataSize]; + random.nextBytes(randomData); + } catch (Exception e) { + CMS.debug("TokenServlet::processComputeRandomData:" + e.toString()); + errorMsg = "Can't generate random data!"; + status = "2"; + } + } + + String randomDataOut = ""; + if (status.equals("0")) { + if (randomData != null && randomData.length == dataSize) { + randomDataOut = + com.netscape.cmsutil.util.Utils.SpecialEncode(randomData); + } else { + status = "2"; + errorMsg = "Can't convert random data!"; + } + } + + if (status.equals("1") && missingParam) { + + if (badParams.endsWith(",")) { + badParams = badParams.substring(0, badParams.length() - 1); + } + errorMsg = "Missing input parameters :" + badParams; + } + + resp.setContentType("text/html"); + String value = ""; + + value = "status=" + status; + if (status.equals("0")) { + value = value + "&DATA=" + randomDataOut; + } + + try { + resp.setContentLength(value.length()); + CMS.debug("TokenServler::processComputeRandomData :outputString.length " + value.length()); + + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (Exception e) { + CMS.debug("TokenServlet::processComputeRandomData " + e.toString()); + } + + if (status.equals("0")) { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_SUCCESS, + ILogger.SUCCESS, + status, + agentId); + } else { + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_COMPUTE_RANDOM_DATA_REQUEST_PROCESSED_FAILURE, + ILogger.FAILURE, + status, + agentId, + errorMsg); + } + + audit(auditMessage); + } + + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest req = cmsReq.getHttpReq(); + HttpServletResponse resp = cmsReq.getHttpResp(); + + IAuthToken authToken = authenticate(cmsReq); + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "execute"); + } catch (Exception e) { + } + + if (authzToken == null) { + + try { + resp.setContentType("text/html"); + String value = "unauthorized="; + CMS.debug("TokenServlet: Unauthorized"); + + resp.setContentLength(value.length()); + OutputStream ooss = resp.getOutputStream(); + ooss.write(value.getBytes()); + ooss.flush(); + mRenderResult = false; + } catch (Exception e) { + CMS.debug("TokenServlet: " + e.toString()); + } + + // cmsReq.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + String temp = req.getParameter("card_challenge"); + mSelectedToken = CMS.getConfigStore().getString("tks.defaultSlot"); + setDefaultSlotAndKeyName(req); + if (temp != null) { + processComputeSessionKey(req, resp); + } else if (req.getParameter("data") != null) { + processEncryptData(req, resp); + } else if (req.getParameter("newKeyInfo") != null) { + processDiversifyKey(req, resp); + } else if (req.getParameter("dataNumBytes") != null) { + processComputeRandomData(req, resp); + } + } + + /** + * Serves HTTP admin request. + * + * @param req HTTP request + * @param resp HTTP response + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + super.service(req, resp); + } +} diff --git a/base/common/src/com/netscape/cms/servlet/wizard/IWizardPanel.java b/base/common/src/com/netscape/cms/servlet/wizard/IWizardPanel.java new file mode 100644 index 000000000..d9d3ddec7 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/wizard/IWizardPanel.java @@ -0,0 +1,111 @@ +// --- 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.wizard; + +import java.io.IOException; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.context.Context; + +import com.netscape.certsrv.property.PropertySet; + +public interface IWizardPanel { + + /** + * Initializes this panel. + */ + public void init(ServletConfig config, int panelno) + throws ServletException; + + public void init(WizardServlet servlet, ServletConfig config, + int panelno, String id) throws ServletException; + + public String getName(); + + public int getPanelNo(); + + public void setId(String id); + + public String getId(); + + public PropertySet getUsage(); + + /** + * Should we skip this panel to the next one? + */ + public boolean shouldSkip(); + + /** + * Cleans up panel so that isPanelDone returns false + */ + public void cleanUp() throws IOException; + + /** + * Is this panel done + */ + public boolean isPanelDone(); + + /** + * Show "Apply" button on frame? + */ + public boolean showApplyButton(); + + /** + * Is this a subPanel? + */ + public boolean isSubPanel(); + + public boolean isLoopbackPanel(); + + /** + * has subPanels? + */ + public boolean hasSubPanel(); + + /** + * Display the panel. + */ + public void display(HttpServletRequest request, + HttpServletResponse response, + Context context); + + /** + * Checks if the given parameters are valid. + */ + public void validate(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException; + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException; + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context); +} diff --git a/base/common/src/com/netscape/cms/servlet/wizard/WizardServlet.java b/base/common/src/com/netscape/cms/servlet/wizard/WizardServlet.java new file mode 100644 index 000000000..42fa88cd9 --- /dev/null +++ b/base/common/src/com/netscape/cms/servlet/wizard/WizardServlet.java @@ -0,0 +1,489 @@ +// --- 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.wizard; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.StringTokenizer; +import java.util.Vector; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import org.apache.velocity.servlet.VelocityServlet; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.cms.servlet.csadmin.Cert; +import com.netscape.cmsutil.crypto.Module; + +/** + * wizard?p=[panel number]&op=usage <= usage in xml + * wizard?p=[panel number]&op=display + * wizard?p=[panel number]&op=next&...[additional parameters]... + * wizard?p=[panel number]&op=apply + * wizard?p=[panel number]&op=back + * wizard?op=menu + * return menu options + */ +public class WizardServlet extends VelocityServlet { + + /** + * + */ + private static final long serialVersionUID = -4513510177445656799L; + private String name = null; + private Vector<IWizardPanel> mPanels = new Vector<IWizardPanel>(); + + public void init(ServletConfig config) throws ServletException { + super.init(config); + + /* load sequence map */ + name = config.getInitParameter("name"); + String panels = config.getInitParameter("panels"); + StringTokenizer st = new StringTokenizer(panels, ","); + int pno = 0; + while (st.hasMoreTokens()) { + String p = st.nextToken(); + StringTokenizer st1 = new StringTokenizer(p, "="); + String id = st1.nextToken(); + String pvalue = st1.nextToken(); + try { + IWizardPanel panel = (IWizardPanel) Class.forName(pvalue).newInstance(); + panel.init(this, config, pno, id); + CMS.debug("WizardServlet: panel name=" + panel.getName()); + mPanels.addElement(panel); + } catch (Exception e) { + CMS.debug("WizardServlet: " + e.toString()); + } + pno++; + } + CMS.debug("WizardServlet: done"); + + } + + public void exposePanels(HttpServletRequest request, + HttpServletResponse response, + Context context) { + Enumeration<IWizardPanel> e = mPanels.elements(); + Vector<IWizardPanel> panels = new Vector<IWizardPanel>(); + while (e.hasMoreElements()) { + IWizardPanel p = (IWizardPanel) e.nextElement(); + panels.addElement(p); + } + context.put("panels", panels); + } + + /** + * Cleans up panels from a particular panel. + */ + public void cleanUpFromPanel(int pno) throws IOException { + /* panel number starts from zero */ + int s = mPanels.size(); + for (int i = pno; i < s; i++) { + IWizardPanel panel = (IWizardPanel) mPanels.elementAt(i); + panel.cleanUp(); + } + } + + public IWizardPanel getPanelByNo(int p) { + IWizardPanel panel = mPanels.elementAt(p); + if (panel.shouldSkip()) { + panel = getPanelByNo(p + 1); + } + return panel; + } + + public Template displayPanel(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("WizardServlet: in display"); + int p = getPanelNo(request); + + if (p == 0) { + CMS.debug("WizardServlet: firstpanel"); + context.put("firstpanel", Boolean.TRUE); + } + if (p == (mPanels.size() - 1)) { + CMS.debug("WizardServlet: lastpanel"); + context.put("lastpanel", Boolean.TRUE); + } + IWizardPanel panel = getPanelByNo(p); + CMS.debug("WizardServlet: panel=" + panel); + + if (panel.showApplyButton() == true) + context.put("showApplyButton", Boolean.TRUE); + else + context.put("showApplyButton", Boolean.FALSE); + + panel.display(request, response, context); + context.put("p", Integer.toString(panel.getPanelNo())); + + try { + return Velocity.getTemplate("admin/console/config/wizard.vm"); + } catch (Exception e) { + } + return null; + } + + public String xml_value_flatten(Object v) { + String ret = ""; + if (v instanceof String) { + ret += v; + } else if (v instanceof Integer) { + ret += ((Integer) v).toString(); + } else if (v instanceof Vector) { + ret += "<Vector>"; + Vector<?> v1 = (Vector<?>) v; + Enumeration<?> e = v1.elements(); + StringBuffer sb = new StringBuffer(); + while (e.hasMoreElements()) { + sb.append(xml_value_flatten(e.nextElement())); + } + ret += sb.toString(); + ret += "</Vector>"; + } else if (v instanceof Module) { // for hardware token + Module m = (Module) v; + ret += "<Module>"; + ret += "<CommonName>" + m.getCommonName() + "</CommonName>"; + ret += "<UserFriendlyName>" + m.getUserFriendlyName() + "</UserFriendlyName>"; + ret += "<ImagePath>" + m.getImagePath() + "</ImagePath>"; + ret += "</Module>"; + } else if (v instanceof Cert) { + Cert m = (Cert) v; + ret += "<CertReqPair>"; + ret += "<Nickname>" + m.getNickname() + "</Nickname>"; + ret += "<Tokenname>" + m.getTokenname() + "</Tokenname>"; + ret += "<Request>" + m.getRequest() + "</Request>"; + ret += "<Certificate>" + m.getCert() + "</Certificate>"; + ret += "<Type>" + m.getType() + "</Type>"; + ret += "<DN>" + m.getDN() + "</DN>"; + ret += "<CertPP>" + m.getCertpp() + "</CertPP>"; + ret += "<KeyOption>" + m.getKeyOption() + "</KeyOption>"; + ret += "</CertReqPair>"; + } else if (v instanceof IWizardPanel) { + IWizardPanel m = (IWizardPanel) v; + ret += "<Panel>"; + ret += "<Id>" + m.getId() + "</Id>"; + ret += "<Name>" + m.getName() + "</Name>"; + ret += "</Panel>"; + } else { + CMS.debug("Error: unknown type " + v.getClass().getName()); + } + return ret; + } + + public String xml_flatten(Context context) { + StringBuffer ret = new StringBuffer(); + Object o[] = context.getKeys(); + for (int i = 0; i < o.length; i++) { + if (o[i] instanceof String) { + String key = (String) o[i]; + if (key.startsWith("__")) { + continue; + } + ret.append("<"); + ret.append(key); + ret.append(">"); + if (key.equals("bindpwd")) { + ret.append("(sensitive)"); + } else { + Object v = context.get(key); + ret.append(xml_value_flatten(v)); + } + ret.append("</"); + ret.append(key); + ret.append(">"); + } + } + return ret.toString(); + } + + public int getPanelNo(HttpServletRequest request) { + int p = 0; + + // panel number can be identified by either + // panel no (p parameter) directly, or + // panel name (panelname parameter). + if (request.getParameter("panelname") != null) { + String name = request.getParameter("panelname"); + for (int i = 0; i < mPanels.size(); i++) { + IWizardPanel panel = mPanels.elementAt(i); + if (panel.getId().equals(name)) { + return i; + } + } + } else if (request.getParameter("p") != null) { + p = Integer.parseInt(request.getParameter("p")); + } + return p; + } + + public String getNameFromPanelNo(int p) { + IWizardPanel wp = mPanels.elementAt(p); + return wp.getId(); + } + + public IWizardPanel getPreviousPanel(int p) { + CMS.debug("getPreviousPanel input p=" + p); + IWizardPanel backpanel = mPanels.elementAt(p - 1); + if (backpanel.isSubPanel()) { + backpanel = mPanels.elementAt(p - 1 - 1); + } + while (backpanel.shouldSkip()) { + backpanel = mPanels.elementAt(backpanel.getPanelNo() - 1); + } + CMS.debug("getPreviousPanel output p=" + backpanel.getPanelNo()); + return backpanel; + } + + public IWizardPanel getNextPanel(int p) { + CMS.debug("getNextPanel input p=" + p); + IWizardPanel panel = mPanels.elementAt(p); + if (p == (mPanels.size() - 1)) { + // p = p; + } else if (panel.isSubPanel()) { + if (panel.isLoopbackPanel()) { + p = p - 1; // Login Panel is a loop back panel + } else { + p = p + 1; + } + } else if (panel.hasSubPanel()) { + p = p + 2; + } else { + p = p + 1; + } + IWizardPanel nextpanel = getPanelByNo(p); + CMS.debug("getNextPanel output p=" + p); + return nextpanel; + } + + public Template goApply(HttpServletRequest request, + HttpServletResponse response, + Context context) { + return goNextApply(request, response, context, true); + } + + public Template goNext(HttpServletRequest request, + HttpServletResponse response, + Context context) { + return goNextApply(request, response, context, false); + } + + /* + * The parameter "stay" is used to indicate "apply" without + * moving to the next panel + */ + public Template goNextApply(HttpServletRequest request, + HttpServletResponse response, + Context context, boolean stay) { + int p = getPanelNo(request); + if (stay == true) + CMS.debug("WizardServlet: in reply " + p); + else + CMS.debug("WizardServlet: in next " + p); + + IWizardPanel panel = mPanels.elementAt(p); + try { + panel.validate(request, response, context); + try { + panel.update(request, response, context); + if (stay == true) { // "apply" + + if (panel.showApplyButton() == true) + context.put("showApplyButton", Boolean.TRUE); + else + context.put("showApplyButton", Boolean.FALSE); + panel.display(request, response, context); + } else { // "next" + IWizardPanel nextpanel = getNextPanel(p); + + if (nextpanel.showApplyButton() == true) + context.put("showApplyButton", Boolean.TRUE); + else + context.put("showApplyButton", Boolean.FALSE); + nextpanel.display(request, response, context); + panel = nextpanel; + } + context.put("errorString", ""); + } catch (Exception e) { + context.put("errorString", e.getMessage()); + panel.displayError(request, response, context); + } + } catch (IOException eee) { + context.put("errorString", eee.getMessage()); + panel.displayError(request, response, context); + } + p = panel.getPanelNo(); + CMS.debug("panel no=" + p); + CMS.debug("panel name=" + getNameFromPanelNo(p)); + CMS.debug("total number of panels=" + mPanels.size()); + context.put("p", Integer.toString(p)); + context.put("panelname", getNameFromPanelNo(p)); + if (p == 0) { + CMS.debug("WizardServlet: firstpanel"); + context.put("firstpanel", Boolean.TRUE); + } + if (p == (mPanels.size() - 1)) { + CMS.debug("WizardServlet: lastpanel"); + context.put("lastpanel", Boolean.TRUE); + } + // this is where we handle the xml request + String xml = request.getParameter("xml"); + if (xml != null && xml.equals("true")) { + CMS.debug("WizardServlet: found xml"); + + response.setContentType("application/xml"); + String xmlstr = xml_flatten(context); + context.put("xml", xmlstr); + try { + return Velocity.getTemplate("admin/console/config/xml.vm"); + } catch (Exception e) { + CMS.debug("Failing to get template" + e); + } + } else { + try { + return Velocity.getTemplate("admin/console/config/wizard.vm"); + } catch (Exception e) { + CMS.debug("Failing to get template" + e); + } + } + return null; + } + + public Template goBack(HttpServletRequest request, + HttpServletResponse response, + Context context) { + int p = getPanelNo(request); + CMS.debug("WizardServlet: in back " + p); + IWizardPanel backpanel = getPreviousPanel(p); + + if (backpanel.showApplyButton() == true) + context.put("showApplyButton", Boolean.TRUE); + else + context.put("showApplyButton", Boolean.FALSE); + backpanel.display(request, response, context); + context.put("p", Integer.toString(backpanel.getPanelNo())); + context.put("panelname", getNameFromPanelNo(backpanel.getPanelNo())); + + p = backpanel.getPanelNo(); + + if (p == 0) { + CMS.debug("WizardServlet: firstpanel"); + context.put("firstpanel", Boolean.TRUE); + } + if (p == (mPanels.size() - 1)) { + CMS.debug("WizardServlet: lastpanel"); + context.put("lastpanel", Boolean.TRUE); + } + try { + return Velocity.getTemplate("admin/console/config/wizard.vm"); + } catch (Exception e) { + } + return null; + } + + public boolean authenticate(HttpServletRequest request, + HttpServletResponse response, + Context context) { + String pin = (String) request.getSession().getAttribute("pin"); + if (pin == null) { + try { + response.sendRedirect("login"); + } catch (IOException e) { + } + return false; + } + return true; + } + + public void outputHttpParameters(HttpServletRequest httpReq) { + CMS.debug("WizardServlet:service() uri = " + httpReq.getRequestURI()); + @SuppressWarnings("unchecked") + Enumeration<String> paramNames = httpReq.getParameterNames(); + while (paramNames.hasMoreElements()) { + String pn = 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 (pn.startsWith("__") || + pn.endsWith("password") || + pn.endsWith("passwd") || + pn.endsWith("pwd") || + pn.equalsIgnoreCase("admin_password_again") || + pn.equalsIgnoreCase("directoryManagerPwd") || + pn.equalsIgnoreCase("bindpassword") || + pn.equalsIgnoreCase("bindpwd") || + pn.equalsIgnoreCase("passwd") || + pn.equalsIgnoreCase("password") || + pn.equalsIgnoreCase("pin") || + pn.equalsIgnoreCase("pwd") || + pn.equalsIgnoreCase("pwdagain") || + pn.equalsIgnoreCase("uPasswd")) { + CMS.debug("WizardServlet::service() param name='" + pn + + "' value='(sensitive)'"); + } else { + CMS.debug("WizardServlet::service() param name='" + pn + + "' value='" + httpReq.getParameter(pn) + "'"); + } + } + } + + public Template handleRequest(HttpServletRequest request, + HttpServletResponse response, + Context context) { + CMS.debug("WizardServlet: process"); + + if (CMS.debugOn()) { + outputHttpParameters(request); + } + + if (!authenticate(request, response, context)) { + CMS.debug("WizardServlet: authentication failure"); + return null; + } + + String op = request.getParameter("op"); /* operation */ + if (op == null) { + op = "display"; + } + CMS.debug("WizardServlet: op=" + op); + CMS.debug("WizardServlet: size=" + mPanels.size()); + + context.put("name", name); + context.put("size", Integer.toString(mPanels.size())); + exposePanels(request, response, context); + + if (op.equals("display")) { + return displayPanel(request, response, context); + } else if (op.equals("next")) { + return goNext(request, response, context); + } else if (op.equals("apply")) { + return goApply(request, response, context); + } else if (op.equals("back")) { + return goBack(request, response, context); + } + return null; + } +} |