diff options
author | PKI Team <PKI Team@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2008-03-18 22:36:57 +0000 |
---|---|---|
committer | PKI Team <PKI Team@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2008-03-18 22:36:57 +0000 |
commit | d0f2e4efbd3eb0f1d7f5a28e7f97c1fb4ec027bb (patch) | |
tree | 7e7473fae8af5ad7e6cda7eabbef787093fc59a7 /pki/base/common/src/com/netscape/cms/servlet | |
parent | 273f8d85df5c31293a908185622b378c8f3cf7e8 (diff) | |
download | pki-d0f2e4efbd3eb0f1d7f5a28e7f97c1fb4ec027bb.tar.gz pki-d0f2e4efbd3eb0f1d7f5a28e7f97c1fb4ec027bb.tar.xz pki-d0f2e4efbd3eb0f1d7f5a28e7f97c1fb4ec027bb.zip |
Initial open source version based upon proprietary Red Hat Certificate System (RHCS) 7.3.
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/trunk@2 c9f7a03b-bd48-0410-a16d-cbbf54688b0b
Diffstat (limited to 'pki/base/common/src/com/netscape/cms/servlet')
195 files changed, 86706 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java new file mode 100644 index 000000000..73779c953 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/ACLAdminServlet.java @@ -0,0 +1,914 @@ +// --- 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.*; +import java.util.*; +import java.math.*; +import java.text.*; +import java.net.*; +import javax.servlet.*; +import javax.servlet.http.*; +//import com.netscape.certsrv.util.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.evaluators.*; +import com.netscape.certsrv.acls.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cmsutil.util.*; + + +/** + * Manage Access Control List configuration + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ACLAdminServlet extends AdminServlet { + + 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; + } + + Locale clientLocale = super.getLocale(req); + + 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; + } + + IUser user = null; + + try { + SessionContext mSC = SessionContext.getContext(); + + user = (IUser) + mSC.get(SessionContext.USER); + } catch (Exception e) { + log(ILogger.LL_FAILURE, e.toString()); + sendResponse(ERROR, + CMS.getUserMessage(getLocale(req), "CMS_ADMIN_SRVLT_PERFORM_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 res = mAuthzMgr.getACLs(); + + while (res.hasMoreElements()) { + ACL acl = (ACL) res.nextElement(); + String desc = acl.getDescription(); + + if (desc == null) + params.add(acl.getName(), ""); + else + params.add(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 en = acl.rights(); + + StringBuffer rights = new StringBuffer(); + + if (en.hasMoreElements()) { + while (en.hasMoreElements()) { + if (rights.length() != 0) { + rights.append(","); + } + String right = (String) en.nextElement(); + + rights.append(right); + } + } + + params.add(Constants.PR_ACL_OPS, rights.toString()); + + en = acl.entries(); + String acis = ""; + + if (en.hasMoreElements()) { + while (en.hasMoreElements()) { + if (acis != "") { + acis += ";"; + } + ACLEntry aclEntry = (ACLEntry) en.nextElement(); + String aci = aclEntry.getACLEntryString(); + + acis += aci; + } + } + + params.add(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 res = mAuthzMgr.aclEvaluatorElements(); + + while (res.hasMoreElements()) { + IAccessEvaluator evaluator = (IAccessEvaluator) res.nextElement(); + + // params.add(evaluator.getType(), evaluator.getDescription()); + params.add(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 res = mAuthzMgr.aclEvaluatorElements(); + + while (res.hasMoreElements()) { + IAccessEvaluator evaluator = (IAccessEvaluator) 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.add(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 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())); + 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/pki/base/common/src/com/netscape/cms/servlet/admin/AdminResources.java b/pki/base/common/src/com/netscape/cms/servlet/admin/AdminResources.java new file mode 100644 index 000000000..7818baaaa --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/AdminResources.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.admin; + + +import java.util.*; + + +/** + * A class represents a resource bundle for the remote admin. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + * @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/pki/base/common/src/com/netscape/cms/servlet/admin/AdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/AdminServlet.java new file mode 100644 index 000000000..8b05f8849 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/AdminServlet.java @@ -0,0 +1,1280 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import javax.servlet.*; +import javax.servlet.http.*; +import java.security.cert.X509Certificate; +import netscape.security.x509.X509CertImpl; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cms.servlet.base.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class AdminServlet extends HttpServlet { + + 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:serice() uri = " + httpReq.getRequestURI()); + Enumeration paramNames = httpReq.getParameterNames(); + while (paramNames.hasMoreElements()) { + String pn = (String)paramNames.nextElement(); + CMS.debug("CMSServlet::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 auditSubjectID = ILogger.UNIDENTIFIED; + 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; + + // a kludge for the desperately pinging console + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + 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(com.netscape.osutil.OSUtil.AtoB(b64s)); + String userid = authCode.substring(0, + authCode.lastIndexOf(':')); + String password = authCode.substring( + authCode.lastIndexOf(':') + 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"); + } catch (EBaseException e) { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_ERROR", + 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) { + Enumeration e = params.getNames(); + + if (e.hasMoreElements()) { + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + String value = java.net.URLEncoder.encode((String) + params.getValue(name)); + + buf.append(java.net.URLEncoder.encode(name) + + "=" + value); + if (e.hasMoreElements()) + 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(); + Enumeration e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = (String) 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.add(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(); + Enumeration e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = (String) 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 e = config.getPropertyNames(); + NameValuePairs params = new NameValuePairs(); + + while (e.hasMoreElements()) { + String s = (String) e.nextElement(); + + params.add(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 + Enumeration e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = (String) 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 groups = null; + + try { + groups = mUG.findGroups("*"); + } catch (Exception e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + StringBuffer membersString = new StringBuffer(); + + while (groups.hasMoreElements()) { + IGroup group = (IGroup) 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.add(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/pki/base/common/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java new file mode 100644 index 000000000..8375cacee --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/AuthAdminServlet.java @@ -0,0 +1,1690 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.util.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.usrgrp.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class AuthAdminServlet extends AdminServlet { + + 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.add(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.add("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 newImpl = null; + + try { + newImpl = Class.forName(classPath); + } 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.add(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 e = mAuths.getPlugins().keys(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + AuthMgrPlugin value = (AuthMgrPlugin) + mAuths.getPlugins().get(name); + + if (value.isVisible()) { + params.add(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.add(name, value.getImplName() + ";invisible;" + enableStr); + } else { + params.add(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. + IAuthManager mgrInst = (IAuthManager) mAuths.get(id); + + mAuths.getInstances().remove((Object) 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.add(Constants.PR_AUTH_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + params.add(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.add(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.add(key, val); + } else { + params.add(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.add(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.add(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); + + Enumeration keys = saveParams.getNames(); + + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + String value = saveParams.getValue(key); + + if (value != null) + rstore.put(key, value); + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/admin/AuthCredentials.java b/pki/base/common/src/com/netscape/cms/servlet/admin/AuthCredentials.java new file mode 100644 index 000000000..65ac8fc04 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/AuthCredentials.java @@ -0,0 +1,100 @@ +// --- 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.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; + + +/** + * Authentication Credentials as input to the authMgr + * <P> + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class AuthCredentials implements IAuthCredentials { + private Hashtable authCreds = null; + // Inserted by bskim + private IArgBlock argblk = null; + // Insert end + + public AuthCredentials() { + authCreds = new Hashtable(); + } + + /** + * 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 ((Object) 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 credentials in this credential + * set. Use the Enumeration methods on the returned object to + * fetch the elements sequentially. + * @return an enumeration of the values in this credential set + * @see java.util.Enumeration + */ + public Enumeration getElements() { + return (authCreds.elements()); + } + + // Inserted by bskim + public void setArgBlock(IArgBlock blk) { + argblk = blk; + return; + } + + // Insert end + + public IArgBlock getArgBlock() { + return argblk; + } + // Insert end +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java new file mode 100644 index 000000000..2cbb06aa1 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/CAAdminServlet.java @@ -0,0 +1,1642 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.util.*; +import netscape.security.x509.*; + +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cmsutil.util.*; +import com.netscape.certsrv.request.IRequestListener; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CAAdminServlet extends AdminServlet { + + 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(); + Enumeration 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_ENABLE)) + continue; + params.add(name, rc.getString(name, "")); + } + + params.add(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(mCA.PROP_NOTIFY_SUBSTORE); + IConfigStore rc = nc.getSubStore(mCA.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(mCA.PROP_NOTIFY_SUBSTORE); + IConfigStore rc = nc.getSubStore(mCA.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(mCA.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(mCA.PROP_REQ_IN_Q_SUBSTORE); + + Enumeration 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_ENABLE)) + continue; + params.add(name, riq.getString(name, "")); + } + + params.add(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(mCA.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(mCA.PROP_REQ_IN_Q_SUBSTORE); + + //set rest of the parameters + Enumeration 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_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())) { + String error = + "Template: " + val + " does not exist or invalid"; + + 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 + Enumeration 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_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())) { + String error = + "Template: " + val + " does not exist or invalid"; + + 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(mCA.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(mCA.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(mCA.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(mCA.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 ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = (ICRLIssuingPoint) ips.nextElement(); + + if (ip != null) { + String ipId = ip.getId(); + + if (ipId != null && ipId.length() > 0) + params.add(ipId, ip.getDescription()); + params.add(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) { + + Enumeration e = req.getParameterNames(); + String value = ""; + + while (e.hasMoreElements()) { + String name = (String) 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.add(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.add(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.add(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.add(Constants.PR_ENABLED, Constants.FALSE); + } else { + params.add(Constants.PR_ENABLED, Constants.TRUE); + } + + IConfigStore crlSubStore = + mCA.getConfigStore().getSubStore(mCA.PROP_CRL_SUBSTORE); + Enumeration crlNames = crlSubStore.getSubStoreNames(); + + while (crlNames.hasMoreElements()) { + String name = (String) 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.add(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.add(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.add(Constants.PR_ENABLED, Constants.FALSE); + } else { + params.add(Constants.PR_ENABLED, Constants.TRUE); + } + + IConfigStore crlSubStore = + mCA.getConfigStore().getSubStore(mCA.PROP_CRL_SUBSTORE); + boolean done = false; + Enumeration crlNames = crlSubStore.getSubStoreNames(); + + while (crlNames.hasMoreElements()) { + String name = (String) 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(mCA.PROP_CRL_SUBSTORE); + boolean done = false; + Enumeration crlNames = crlSubStore.getSubStoreNames(); + + while (crlNames.hasMoreElements()) { + String name = (String) 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; + Enumeration 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; + 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(mCA.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(ipId); + IConfigStore crlExtsSubStore = + crlSubStore.getSubStore(mCA.PROP_CRLEXT_SUBSTORE); + + String id = req.getParameter(Constants.RS_ID); + + if (id != null) { + IConfigStore crlExtSubStore = crlExtsSubStore.getSubStore(id); + + Enumeration 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_CRLEXT_IMPL_NAME)) + continue; + if (name.equals("RULENAME")) + continue; + String value = req.getParameter(name); + + params.add(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 = mCA.PROP_MASTER_CRL; + } + + IConfigStore config = mCA.getConfigStore(); + IConfigStore crlsSubStore = config.getSubStore(mCA.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(id); + IConfigStore crlExtsSubStore = crlSubStore.getSubStore(mCA.PROP_CRLEXT_SUBSTORE); + + if (crlExtsSubStore != null) { + Enumeration enumExts = crlExtsSubStore.getSubStoreNames(); + + while (enumExts.hasMoreElements()) { + String extName = (String) enumExts.nextElement(); + boolean crlExtEnabled = false; + IConfigStore crlExtSubStore = crlExtsSubStore.getSubStore(extName); + Enumeration properties = crlExtSubStore.getPropertyNames(); + + while (properties.hasMoreElements()) { + String name = (String) properties.nextElement(); + + if (name.equals(Constants.PR_ENABLE)) { + crlExtEnabled = crlExtSubStore.getBoolean(name, false); + } + } + params.add(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 ips = mCA.getCRLIssuingPoints(); + if (ips.hasMoreElements()) { + ICRLIssuingPoint ip = (ICRLIssuingPoint) 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 = mCA.PROP_MASTER_CRL; + } + ICRLIssuingPoint ip = mCA.getCRLIssuingPoint(id); + + //Save New Settings to the config file + IConfigStore config = mCA.getConfigStore(); + IConfigStore crlsSubStore = config.getSubStore(mCA.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(id); + + //set reset of the parameters + Enumeration 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_ENABLE)) + continue; + String value = req.getParameter(name); + + params.add(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 = mCA.PROP_MASTER_CRL; + } + IConfigStore crlsSubStore = + mCA.getConfigStore().getSubStore(mCA.PROP_CRL_SUBSTORE); + IConfigStore crlSubStore = crlsSubStore.getSubStore(id); + + Enumeration 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_ENABLE)) + continue; + params.add(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"); + } + + Enumeration enum1 = req.getParameterNames(); + NameValuePairs params = new NameValuePairs(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = (String) enum1.nextElement(); + + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.OP_TYPE)) + continue; + + params.add(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"); + } + + Enumeration enum1 = req.getParameterNames(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = (String) 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) { + Enumeration enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) 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) { + Enumeration enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) 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(mCA.PROP_ENABLE_PAST_CATIME, "false"); + params.add(Constants.PR_VALIDITY, value); + + getSigningAlgConfig(params); + getSerialConfig(params); + getMaxSerialConfig(params); + + sendResponse(SUCCESS, null, params, resp); + } + + private void getSigningAlgConfig(NameValuePairs params) { + params.add(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.add(Constants.PR_ALL_ALGORITHMS, algorStr.toString()); + } + + private void getSerialConfig(NameValuePairs params) { + params.add(Constants.PR_SERIAL, + mCA.getStartSerial()); + } + + private void getMaxSerialConfig(NameValuePairs params) { + params.add(Constants.PR_MAXSERIAL, + mCA.getMaxSerial()); + } + + private void setGeneralConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + ISubsystem eeGateway = null; + + /* + ISubsystem eeGateway = + SubsystemRegistry.getInstance().get("eeGateway"); + */ + IConfigStore eeConfig = null; + + if (eeGateway != null) + eeConfig = eeGateway.getConfigStore(); + IConfigStore caConfig = mCA.getConfigStore(); + + Enumeration enum1 = req.getParameterNames(); + boolean restart = false; + + mCA.setMaxSerial(""); + while (enum1.hasMoreElements()) { + String key = (String) 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); + } + + /** + * Retrieves configuration parameters of certificate + * authority. + */ + private synchronized void getConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + // validate + super.getConfig(mCA.getConfigStore(), req, resp); + } + + /** + * Sets configuration parameters of certificate + * authority. + */ + private synchronized void setConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + super.setConfig(mCA.getConfigStore(), req, resp); + // XXX - commit changes + } + + /** + * Lists configuration store parameters. + */ + private synchronized void listConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + super.listConfig(mCA.getConfigStore(), req, resp); + } + + /** + * Locks a request so that no one can modify it except + * owner. + */ + private synchronized void lockRequest(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + // XXX + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Locks certificate record so that no one can + * modify it except owner. + */ + private synchronized void lockCertRecord(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Modifies a cert record. + */ + private synchronized void modifyCertRecord(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + NameValuePairs params = new NameValuePairs(); + + // XXX + sendResponse(SUCCESS, null, params, 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/pki/base/common/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java new file mode 100644 index 000000000..5e53c6588 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/CMSAdminServlet.java @@ -0,0 +1,3541 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.CertificateEncodingException; +import javax.servlet.*; +import javax.servlet.http.*; +import org.mozilla.jss.CryptoManager.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.*; +import netscape.security.x509.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.selftests.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.tks.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.cert.ICrossCertPairSubsystem; +import com.netscape.cmsutil.util.*; +import com.netscape.cms.servlet.common.CMSGateway; +import org.mozilla.jss.util.Password; +import org.mozilla.jss.util.PasswordCallback; +import org.mozilla.jss.util.ConsolePasswordCallback; +import org.mozilla.jss.util.IncorrectPasswordException; +import com.netscape.symkey.*; + +/** + * A class representings an administration servlet. This + * servlet is responsible to serve Certificate Server + * level administrative operations such as configuration + * parameter updates. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public final class CMSAdminServlet extends AdminServlet { + + 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"; + + // 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 (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); + } + } 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.add(Constants.PR_NT, Constants.TRUE); + else + params.add(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.add(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.add(Constants.PR_ALL_NICKNAMES, jssSubSystem.getAllCerts()); + + sendResponse(SUCCESS, null, params, resp); + } + + private boolean isSubsystemInstalled(String subsystem) { + Enumeration e = CMS.getSubsystems(); + + while (e.hasMoreElements()) { + String type = ""; + 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 e = CMS.getSubsystems(); + boolean isCAInstalled = false; + boolean isRAInstalled = false; + boolean isKRAInstalled = false; + boolean isOCSPInstalled = false; + boolean isTKSInstalled = false; + + while (e.hasMoreElements()) { + String type = ""; + 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; + else if (sys instanceof IOCSPAuthority) + isOCSPInstalled = true; + else if (sys instanceof ITKSAuthority) + isTKSInstalled = true; + + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String caTokenName = ""; + + NameValuePairs params = new NameValuePairs(); + + params.add(Constants.PR_CIPHER_VERSION, + jssSubSystem.getCipherVersion()); + params.add(Constants.PR_CIPHER_FORTEZZA, jssSubSystem.isCipherFortezza()); + params.add(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.add(Constants.PR_TOKEN_PREFIX + tokenName, certs); + } + + params.add(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.add(Constants.PR_CERT_CA, getCertNickname(caNickName)); + } + + if (isRAInstalled) { + IRegistrationAuthority ra = (IRegistrationAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_RA); + String raNickname = ra.getNickname(); + + params.add(Constants.PR_CERT_RA, getCertNickname(raNickname)); + } + + if (isKRAInstalled) { + IKeyRecoveryAuthority kra = (IKeyRecoveryAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_KRA); + String kraNickname = kra.getNickname(); + + params.add(Constants.PR_CERT_TRANS, getCertNickname(kraNickname)); + } + if (isTKSInstalled) { + ITKSAuthority tks = (ITKSAuthority) + CMS.getSubsystem(CMS.SUBSYSTEM_TKS); + } + String nickName = CMS.getServerCertNickname(); + + params.add(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 { + Enumeration enum1 = req.getParameterNames(); + NameValuePairs params = new NameValuePairs(); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + jssSubSystem.getInternalTokenName(); + Enumeration e = CMS.getSubsystems(); + boolean isCAInstalled = false; + boolean isRAInstalled = false; + boolean isKRAInstalled = false; + boolean isOCSPInstalled = false; + boolean isTKSInstalled = false; + + while (e.hasMoreElements()) { + String type = ""; + 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; + else if (sys instanceof IOCSPAuthority) + isOCSPInstalled = true; + else if (sys instanceof ITKSAuthority) + isTKSInstalled = true; + } + + ICertificateAuthority ca = null; + IRegistrationAuthority ra = null; + IKeyRecoveryAuthority kra = null; + ITKSAuthority tks = 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); + if (isTKSInstalled) + tks = (ITKSAuthority) CMS.getSubsystem(CMS.SUBSYSTEM_TKS); + + 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 e = CMS.getSubsystems(); + StringBuffer buff = new StringBuffer(); + + 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.add(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.add(Constants.PR_STAT_INSTALLDATE, installdate); + } catch (Exception e) { + } + + try { + String version = cs.getString(Constants.PR_STAT_VERSION, ""); + params.add(Constants.PR_STAT_VERSION, version); + } catch (Exception e) { + } + + try { + String instanceId = cs.getString(Constants.PR_STAT_INSTANCEID, ""); + params.add(Constants.PR_STAT_INSTANCEID, instanceId); + } catch (Exception e) { + } + + params.add(Constants.PR_STAT_STARTUP, + (new Date(CMS.getStartupTime())).toString()); + params.add(Constants.PR_STAT_TIME, + (new Date(System.currentTimeMillis())).toString()); + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Modifies network information. + */ + private void modifyNetworkConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + /* + HTTPSubsystem eeGateway = (HTTPSubsystem) + SubsystemRegistry.getInstance().get("eeGateway"); + RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance(); + AgentGateway agent = (AgentGateway)mReg.get(AgentGateway.ID); + + Enumeration enum1 = req.getParameterNames(); + + String eeHTTPportString = null; + String eeHTTPSportString = null; + String agentHTTPSportString = null; + String radminHTTPSportString = null; + + String gatewayBacklog = "15"; + + // eeHTTPEnabled corresponds to the checkbox which enables the + // HTTP EE port + String eeHTTPEnabled = Constants.FALSE; + + while (enum1.hasMoreElements()) { + String key = (String)enum1.nextElement(); + String value = (String)req.getParameter(key); + + if (key.equals(Constants.PR_AGENT_S_BACKLOG)) { + agent.setHTTPSBacklog(value); + } else if (key.equals(Constants.PR_GATEWAY_S_BACKLOG)) { + eeGateway.setHTTPSBacklog(value); + } else if (key.equals(Constants.PR_ADMIN_S_BACKLOG)) { + raAdmin.setHTTPSBacklog(value); + } else if (key.equals(Constants.PR_GATEWAY_BACKLOG)) { + gatewayBacklog = value; + } else if (key.equals(Constants.PR_GATEWAY_PORT_ENABLED)) { + eeHTTPEnabled = value; + } + } + + + eeHTTPportString = req.getParameter(Constants.PR_GATEWAY_PORT); + eeHTTPSportString = req.getParameter(Constants.PR_GATEWAY_S_PORT); + agentHTTPSportString= req.getParameter(Constants.PR_AGENT_S_PORT); + radminHTTPSportString= req.getParameter(Constants.PR_ADMIN_S_PORT); + + + int eeHTTPport=0; + int eeHTTPSport=0; + int agentHTTPSport=0; + int radminHTTPSport=0; + if (eeHTTPportString != null) eeHTTPport = Integer.parseInt(eeHTTPportString); + if (eeHTTPSportString != null) eeHTTPSport = Integer.parseInt(eeHTTPSportString); + if (agentHTTPSportString != null) agentHTTPSport = Integer.parseInt(agentHTTPSportString); + if (radminHTTPSportString != null) radminHTTPSport = Integer.parseInt(radminHTTPSportString); + + + String portName=""; + int portnum; + try { + + // EE HTTP is special, since it has it's own checkbox for enabling/disabling + if (eeHTTPEnabled.equals(Constants.TRUE) && + eeHTTPport != 0 && + eeHTTPport != eeGateway.getHTTPPort()) + { + portName = "End-entity"; + checkPortAvailable(eeHTTPport); + } + + if (eeHTTPSport != 0 && eeHTTPSport != eeGateway.getHTTPSPort()) { + portName = "SSL End-entity"; + checkPortAvailable(eeHTTPSport); + } + if (agentHTTPSport != 0 && agentHTTPSport != agent.getHTTPSPort()) { + portName = "Agent"; + checkPortAvailable(agentHTTPSport); + } + if (radminHTTPSport != 0 && radminHTTPSport != raAdmin.getHTTPSPort()) { + portName = "Remote Admin"; + checkPortAvailable(radminHTTPSport); + } + + // If any of the above ports are not available, an exception + // will be thrown and these methods below will not be called + + if (eeHTTPEnabled.equals(Constants.TRUE)) { + eeGateway.setHTTPPort(eeHTTPport); + } + eeGateway.setHTTPSPort(eeHTTPSport); + agent.setHTTPSPort(agentHTTPSport); + raAdmin.setHTTPSPort(radminHTTPSport); + + } catch (IOException e) { + // send 'port in use' error + sendResponse(ERROR, portName+" "+e.getMessage(), null, resp); + // we do not want to save the config in this case + return; + } + + eeGateway.setHTTPBacklog(gatewayBacklog); + eeGateway.setHTTPPortEnable(eeHTTPEnabled); + + mConfig.commit(true); + sendResponse(RESTART, null, null, resp); + */ + } + + /** + * Check if the port is available for binding. + * @throws IOException if not available + */ + + private void checkPortAvailable(int port) + throws IOException { + try { + // see if the port is being used by somebody else + ServerSocket ss = new ServerSocket(port); + + ss.close(); + } catch (Exception e) { + throw new IOException("port " + port + " is in use. Please select another port"); + } + } + + /** + * Reads network information. + */ + private void readNetworkConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + NameValuePairs params = new NameValuePairs(); + + getEENetworkConfig(params); + getAdminConfig(params); + getAgentConfig(params); + + sendResponse(SUCCESS, null, params, resp); + } + + private void getEENetworkConfig(NameValuePairs params) + throws EBaseException { + + /* + HTTPSubsystem eeGateway = + (HTTPSubsystem)mReg.get("eeGateway"); + if (eeGateway == null) { + // i.e. standalone DRM + params.add(Constants.PR_GATEWAY_S_PORT, "-1"); + params.add(Constants.PR_GATEWAY_PORT, "-1"); + params.add(Constants.PR_GATEWAY_S_BACKLOG, "-1"); + params.add(Constants.PR_GATEWAY_BACKLOG,"-1"); + params.add(Constants.PR_GATEWAY_PORT_ENABLED,"false"); + } else { + params.add(Constants.PR_GATEWAY_S_PORT, + ""+eeGateway.getHTTPSPort()); + params.add(Constants.PR_GATEWAY_PORT, + ""+eeGateway.getHTTPPort()); + params.add(Constants.PR_GATEWAY_S_BACKLOG, + ""+eeGateway.getHTTPBacklog()); + params.add(Constants.PR_GATEWAY_BACKLOG, + ""+eeGateway.getHTTPSBacklog()); + params.add(Constants.PR_GATEWAY_PORT_ENABLED, + eeGateway.getHTTPPortEnable()); + } + */ + } + + private void getAdminConfig(NameValuePairs params) throws EBaseException { + + /* + RemoteAdmin raAdmin = (RemoteAdmin)RemoteAdmin.getInstance(); + params.add(Constants.PR_ADMIN_S_PORT, ""+raAdmin.getHTTPSPort()); + params.add(Constants.PR_ADMIN_S_BACKLOG,""+raAdmin.getHTTPSBacklog()); + */ + } + + private void getAgentConfig(NameValuePairs params) throws EBaseException { + + /* + AgentGateway agent = (AgentGateway)mReg.get(AgentGateway.ID); + params.add(Constants.PR_AGENT_S_PORT, ""+agent.getHTTPSPort()); + params.add(Constants.PR_AGENT_S_BACKLOG,""+agent.getHTTPSBacklog()); + */ + } + + /** + * Modifies database information. + */ + private void setDBConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + + IConfigStore dbConfig = mConfig.getSubStore(PROP_INTERNAL_DB); + Enumeration 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(); + Enumeration 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) + { + String symKeys = SessionKey.GenMasterKey(selectedToken,newKeyName); + CMS.getConfigStore().putString("tks.defaultSlot", selectedToken); + String masterKeyPrefix = CMS.getConfigStore().getString("tks.master_key_prefix", null); + + SessionKey.SetDefaultPrefix(masterKeyPrefix); + params.add(Constants.PR_KEY_LIST, newKeyName); + params.add(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(); + Enumeration e = req.getParameterNames(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + + if (name.equals(Constants.PR_TOKEN_LIST)) + { + String selectedToken = req.getParameter(name); + + int count = 0; + int keys_found = 0; + + 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.add(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(); + Enumeration 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.add(name, ldapConfig.getString(name, "Constants.FALSE")); + else + params.add(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.add(Constants.PR_SERVER_NAME, + dbConfig.getString("host")); + params.add(Constants.PR_PORT, + dbConfig.getString("port")); + sendResponse(SUCCESS, null, params, resp); + } + + private void loggedInToken(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + Enumeration 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 { + Enumeration 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.add(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(); + Enumeration 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 serverID = ""; + String otherNickname = ""; + String certSubType = ""; + + 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_SERVER_ID)) { + serverID = value; + } else if (key.equals(Constants.PR_NICKNAME)) { + otherNickname = value; + } else if (key.equals(Constants.PR_CERTIFICATE_SUBTYPE)) { + certSubType = 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("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.add(Constants.PR_CSR, certReq); + params.add(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 { + Enumeration enum1 = req.getParameterNames(); + String pkcs = ""; + String type = ""; + String tokenName = Constants.PR_INTERNAL_TOKEN_NAME; + String keyType = "RSA"; + int keyLength = 512; + String subjectName = ""; + KeyCertData properties = new KeyCertData(); + String pathname = ""; + + String configPath = ""; + String newtokenname = null; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals("pathname")) { + configPath = mConfig.getString("instanceRoot", "") + + File.separator + "conf" + File.separator; + pathname = configPath + value; + } else { + 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); + IDBSubsystem dbs = (IDBSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_DBS); + 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; + + // create a new CA certificate or ssl server cert + if (properties.getKeyLength() != null) { + keyType = properties.getKeyType(); + String keyLen = properties.getKeyLength(); + PQGParams pqgParams = null; + + if (keyType.equals("DSA")) { + pqgParams = jssSubSystem.getCAPQG(Integer.parseInt(keyLen), + mConfig); + //properties.put(Constants.PR_PQGPARAMS, pqgParams); + } + pair = jssSubSystem.getKeyPair(properties); + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) { + caKeyPair = pair; + defaultSigningAlg = getDefaultSigningAlg(keyType, + properties.getHashType()); + } + // 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)); + */ + } + + if (!certType.equals(Constants.PR_CA_SIGNING_CERT)) { + caKeyPair = jssSubSystem.getKeyPair(canickname); + updateCASignature(canickname, properties, jssSubSystem); + } + + 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()); + + /* 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 { + 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(); + + 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); + } + } + } + } + + if (certType.equals(Constants.PR_CA_SIGNING_CERT)) + signingUnit.setDefaultAlgorithm(defaultSigningAlg); + 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) { + // 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 getDefaultSigningAlg(String keyType, String messageDigest) { + if (keyType.equals("RSA")) { + if (messageDigest.equals("MD2")) { + return "MD2withRSA"; + } else if (messageDigest.equals("MD5")) { + return "MD5withRSA"; + } else if (messageDigest.equals("SHA1")) { + return "SHA1withRSA"; + } else if (messageDigest.equals("SHA256")) { + return "SHA256withRSA"; + } else if (messageDigest.equals("SHA512")) { + return "SHA512withRSA"; + } + } else if (keyType.equals("DSA")) { + if (messageDigest.equals("SHA1")) { + return "SHA1withDSA"; + } + } + return null; + } + + 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 = ""; + Enumeration 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). + // + + try { + jssSubSystem.importCert(pkcs, nicknameWithoutTokenName, + certType); + } catch (EBaseException e) { + // 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; + } + } + + 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); + } + + // 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) { + // 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 certType = ""; + String pathname = ""; + String serverRoot = ""; + String serverID = ""; + String certpath = ""; + Enumeration 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(Constants.RS_ID)) + certType = 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 = (byte[]) (com.netscape.osutil.OSUtil.AtoB(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.add(Constants.PR_NICKNAME, "FBCA cross-signed cert"); + results.add(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 { + Enumeration 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.add(Constants.PR_NICKNAME, nickname); + results.add(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 { + Enumeration 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.add(nickname, print); + + sendResponse(SUCCESS, null, pairs, resp); + } + + private void getRootCertTrustBit(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + Enumeration 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 trustbit = jssSubSystem.getRootCertTrustBit(nickname, + serialno, issuername); + pairs.add(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 { + Enumeration 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 { + + Enumeration 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 { + Enumeration enum1 = req.getParameterNames(); + String keyType = "RSA"; + String keyLen = "512"; + String certType = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.PR_CERTIFICATE_TYPE)) { + certType = value; + } else if (key.equals(Constants.PR_KEY_TYPE)) { + keyType = value; + } else if (key.equals(Constants.PR_KEY_LENGTH)) { + keyLen = value; + } + } + int keyLength = Integer.parseInt(keyLen); + int minKey = mConfig.getInteger( + ConfigConstants.PR_RSA_MIN_KEYLENGTH, 512); + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + // jssSubSystem.checkKeyLength(keyType, keyLength, certType, minKey); + sendResponse(SUCCESS, null, null, resp); + } + + private void validateCertExtension(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + Enumeration 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(); + Enumeration enum1 = req.getParameterNames(); + + String nickname = ""; + String keyType = "RSA"; + String keyLen = "512"; + String certType = ""; + String configDir = ""; + + while (enum1.hasMoreElements()) { + String key = (String) enum1.nextElement(); + String value = req.getParameter(key); + + if (key.equals(Constants.RS_ID)) { + certType = value; + nickname = getNickname(value); + break; + } + } + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + String subjectName = jssSubSystem.getSubjectDN(nickname); + + params.add(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(); + Enumeration enum1 = req.getParameterNames(); + + String nickname = ""; + String keyType = "RSA"; + String keyLen = "512"; + String certType = ""; + String configDir = ""; + + 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.add(Constants.PR_SUBJECT_NAME, subjectName); + sendResponse(SUCCESS, null, params, resp); + } + + public void setRootCertTrust(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + 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"); + + ICryptoSubsystem jssSubSystem = (ICryptoSubsystem) + CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + jssSubSystem.setRootCertTrust(nickname, serialno, issuername, trust); + 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(); + + // ensure that any low-level exceptions are reported + // to the signed audit log and stored as failures + try { + Enumeration 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 . . ."); + } + + Enumeration 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.add(Constants.PR_RUN_SELFTESTS_ON_DEMAND_CLASS, + CMSAdminServlet.class.getName()); + results.add(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 = com.netscape.osutil.OSUtil.BtoA(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/pki/base/common/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java new file mode 100644 index 000000000..8a02edce9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/JobsAdminServlet.java @@ -0,0 +1,997 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.util.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.jobs.*; +import com.netscape.certsrv.apps.*; + + +/** + * A class representing an administration servlet for the + * Jobs Scheduler and it's scheduled jobs. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class JobsAdminServlet extends AdminServlet { + // ... 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)) { + 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.add(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 e = mJobsSched.getPlugins().keys(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + JobPlugin value = (JobPlugin) + mJobsSched.getPlugins().get(name); + + params.add(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 e = mJobsSched.getInstances().keys(); + e.hasMoreElements();) { + String name = (String) e.nextElement(); + IJob value = (IJob) + mJobsSched.getInstances().get((Object) name); + + // params.add(name, value.getImplName()); + params.add(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 e = mJobsSched.getInstances().elements(); + e.hasMoreElements();) { + IJob jobs = (IJob) 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. + IJob jobInst = (IJob) mJobsSched.getInstances().get(id); + + mJobsSched.getInstances().remove((Object) 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.add(Constants.PR_JOBS_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.length; i++) { + params.add(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.add(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.add(key, val); + } else { + params.add(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.add(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.add(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.add(Constants.PR_ENABLE, + config.getString(IJobsScheduler.PROP_ENABLED, + Constants.FALSE)); + // default 1 minute + params.add(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); + + Enumeration keys = saveParams.getNames(); + + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + String value = saveParams.getValue(key); + + if (!value.equals("")) + rstore.put(key, value); + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java new file mode 100644 index 000000000..33de710ca --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/KRAAdminServlet.java @@ -0,0 +1,817 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.password.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.usrgrp.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class KRAAdminServlet extends AdminServlet { + 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; + } + 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 (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_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; + } + } + } 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); + } + + /** + * Changes M-N scheme. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_DRM used when configuring + * DRM (Key recovery scheme, change of any secret component) + * </ul> + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception EBaseException an error has occurred + */ + private synchronized void changeMNScheme(HttpServletRequest req, + HttpServletResponse resp) throws 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 { + try { + NameValuePairs params = new NameValuePairs(); + String recN = getParameter(req, + Constants.PR_RECOVERY_N); + String recM = getParameter(req, + Constants.PR_RECOVERY_M); + String oldAgents = getParameter(req, + Constants.PR_OLD_RECOVERY_AGENT); + String agents = getParameter(req, + Constants.PR_RECOVERY_AGENT); + + if (recN == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EKRAException( + CMS.getLogMessage("KRA_INVALID_N")); + } + + if (recM == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EKRAException( + CMS.getLogMessage("KRA_INVALID_M")); + } + + if (recN != null && recM != null && oldAgents != null + && agents != null) { + int nVal = Integer.parseInt(recN); + + int mVal = Integer.parseInt(recM); + + Credential oldcreds[] = + parseCredentialStr(oldAgents); + + if (oldcreds == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EKRAException( + CMS.getLogMessage("KRA_INVALID_PASSWORD")); + } + + Credential creds[] = + parseCredentialStr(agents); + + if (creds == null) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EKRAException( + CMS.getLogMessage("KRA_INVALID_PASSWORD")); + } else { + for (int i = 0; i < creds.length; i++) { + Credential credential = creds[i]; + String pass = credential.getPassword(); + IPasswordCheck checker = CMS.getPasswordChecker(); + + if (!checker.isGoodPassword(pass)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(checker.getReason(pass)); + } + } + } + if (mKRA.getStorageKeyUnit().changeAgentMN( + nVal, mVal, oldcreds, creds)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + // successful operation + sendResponse(SUCCESS, null, params, + resp); + return; + } + } + } catch (IOException e) { + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_INVALID_OPERATION")); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } + } + + /** + * Changes recovery agent password. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_DRM used when configuring + * DRM (Key recovery scheme, change of any secret component) + * </ul> + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception EBaseException an error has occurred + */ + private synchronized void changeAgentPwd(HttpServletRequest req, + HttpServletResponse resp) throws 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 { + try { + String id = getParameter(req, Constants.RS_ID); + String oldpwd = getParameter(req, + Constants.PR_OLD_AGENT_PWD); + String newpwd = getParameter(req, + Constants.PR_AGENT_PWD); + IPasswordCheck checker = CMS.getPasswordChecker(); + + if (!checker.isGoodPassword(newpwd)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(checker.getReason(newpwd)); + } + + if (mKRA.getStorageKeyUnit().changeAgentPassword(id, + oldpwd, newpwd)) { + NameValuePairs params = new NameValuePairs(); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, resp); + return; + } else { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EKRAException( + CMS.getLogMessage("KRA_INVALID_PASSWORD")); + } + } catch (IOException e) { + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_INVALID_OPERATION")); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } + } + + /** + * Modifies auto recovery configuration. + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_DRM used when configuring + * DRM (Key recovery scheme, change of any secret component) + * </ul> + * @param req HTTP servlet request + * @param resp HTTP servlet response + * @exception EBaseException an error has occurred + */ + private synchronized void modifyAutoRecoveryConfig( + HttpServletRequest req, HttpServletResponse resp) + throws 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 { + try { + NameValuePairs params = new NameValuePairs(); + String autoOn = getParameter(req, + Constants.PR_AUTO_RECOVERY_ON); + String agents = getParameter(req, + Constants.PR_RECOVERY_AGENT); + + if (autoOn.equals(Constants.TRUE)) { + Credential creds[] = parseCredentialStr( + agents); + + if (mKRA.setAutoRecoveryState(creds, true)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, + resp); + return; + } + } else if (autoOn.equals(Constants.FALSE)) { + if (mKRA.setAutoRecoveryState(null, false)) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.SUCCESS, + auditParams(req)); + + audit(auditMessage); + + sendResponse(SUCCESS, null, params, + resp); + return; + } + } + } catch (IOException e) { + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + throw new EBaseException(CMS.getLogMessage("BASE_INVALID_OPERATION")); + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + auditSubjectID, + ILogger.FAILURE, + auditParams(req)); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + } + } + + /** + * Reads auto recovery status. + * + * @param req HTTP request + * @param resp HTTP response + */ + private synchronized void readAutoRecoveryConfig( + HttpServletRequest req, HttpServletResponse resp) + throws EBaseException { + try { + NameValuePairs params = new NameValuePairs(); + + params.add(Constants.PR_AUTO_RECOVERY_ON, + mKRA.getAutoRecoveryState() ? + Constants.TRUE : Constants.FALSE); + sendResponse(SUCCESS, null, params, resp); + } catch (IOException e) { + throw new EBaseException( + CMS.getLogMessage("BASE_INVALID_OPERATION")); + } + } + + /** + * Reads recovery configuration. + * + * @param req HTTP request + * @param resp HTTP response + */ + private synchronized void readRecoveryConfig( + HttpServletRequest req, HttpServletResponse resp) + throws EBaseException { + try { + IStorageKeyUnit sku = mKRA.getStorageKeyUnit(); + NameValuePairs params = new NameValuePairs(); + + params.add(Constants.PR_RECOVERY_N, + Integer.toString(sku.getNoOfAgents())); + params.add(Constants.PR_RECOVERY_M, + Integer.toString(sku.getNoOfRequiredAgents())); + Enumeration e = sku.getAgentIdentifiers(); + StringBuffer as = new StringBuffer(); + + while (e.hasMoreElements()) { + as.append((String)e.nextElement()); + if (e.hasMoreElements()) { + as.append(","); + } + } + params.add(Constants.PR_RECOVERY_AGENT, as.toString()); + sendResponse(SUCCESS, null, params, resp); + } catch (IOException e) { + throw new EBaseException( + CMS.getLogMessage("BASE_INVALID_OPERATION")); + } + } + + /** + * Reads information about auto recovery agents. + * + * @param req HTTP request + * @param resp HTTP response + */ + private synchronized void readAutoRecoveryAgents( + HttpServletRequest req, HttpServletResponse resp) + throws EBaseException { + try { + // send the entire list anyway + NameValuePairs params = new NameValuePairs(); + Enumeration e = mKRA.getAutoRecoveryIDs(); + StringBuffer users = new StringBuffer(); + + while (e.hasMoreElements()) { + users.append((String) e.nextElement()); + if (e.hasMoreElements()) { + users.append(","); + } + } + params.add(Constants.PR_GROUP_USER, users.toString()); + params.add(Constants.PR_GROUP_DESC, + "Auto Recovery Agents"); // XXX - localized + sendResponse(SUCCESS, null, params, resp); + } catch (IOException e) { + throw new EBaseException( + CMS.getLogMessage("BASE_INVALID_OPERATION")); + } + } + + /** + * Modifies information about auto recovery agents. + * + * @param req HTTP request + * @param resp HTTP response + */ + private synchronized void modifyAutoRecoveryAgents( + HttpServletRequest req, HttpServletResponse resp) + throws EBaseException { + Vector v = new Vector(); + String users = getParameter(req, + Constants.PR_GROUP_USER); + StringTokenizer st = new StringTokenizer(users, ","); + + while (st.hasMoreTokens()) { + v.addElement(st.nextToken()); + } + String desc = getParameter(req, + Constants.PR_GROUP_DESC); + String agents = getParameter(req, + Constants.PR_RECOVERY_AGENT); + Credential creds[] = parseCredentialStr( + agents); + // XXX - check if the given password matched + // put ids into hashtable so that we can + // figure out what should be saved and deleted + Enumeration e = mKRA.getAutoRecoveryIDs(); + Hashtable h = new Hashtable(); + + while (e.hasMoreElements()) { + h.put(e.nextElement(), ""); + } + + // go through each of the user in the new list + for (int i = 0; i < v.size(); i++) { + String key = (String) v.elementAt(i); + + if (h.containsKey(key)) { + h.remove(key); + } else { + mKRA.addAutoRecovery(key, creds); + } + } + + // delete all the unreferenced + Enumeration dels = h.keys(); + + while (dels.hasMoreElements()) { + mKRA.removeAutoRecovery((String) + dels.nextElement()); + } + } + + /** + * Parses uid0=pwd0,uid1=pwd1,... into AgentCredential. + * + * @param s credential string + * @return a list of credentials + */ + private Credential[] parseCredentialStr(String s) { + StringTokenizer st = new StringTokenizer(s, ","); + Vector v = new Vector(); + + while (st.hasMoreTokens()) { + String a = st.nextToken(); + StringTokenizer st0 = new StringTokenizer(a, "="); + + v.addElement(new Credential(st0.nextToken(), + st0.nextToken())); + } + Credential ac[] = new Credential[v.size()]; + + v.copyInto(ac); + return ac; + } + + /* + * 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 = mKRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(mKRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(mKRA.PROP_REQ_IN_Q_SUBSTORE); + + Enumeration 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_ENABLE)) + continue; + params.add(name, riq.getString(name, "")); + } + + params.add(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 + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_CONFIG_DRM used when configuring + * DRM (Key recovery scheme, change of any secret component) + * </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 setNotificationRIQConfig(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 { + IConfigStore config = mKRA.getConfigStore(); + IConfigStore nc = + config.getSubStore(mKRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(mKRA.PROP_REQ_IN_Q_SUBSTORE); + + //set rest of the parameters + Enumeration 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_ENABLE)) + continue; + String val = req.getParameter(name); + + riq.putString(name, val); + mKRA.getRequestInQListener().set(name, val); + } + + // set enable flag + String enabledString = req.getParameter(Constants.PR_ENABLE); + + riq.putString(PROP_ENABLED, enabledString); + mKRA.getRequestInQListener().set(PROP_ENABLED, enabledString); + + commit(true); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CONFIG_DRM, + 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_DRM, + 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_DRM, + 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_DRM, + // auditSubjectID, + // ILogger.FAILURE, + // auditParams( req ) ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit3; + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/admin/LogAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/LogAdminServlet.java new file mode 100644 index 000000000..f25c2dcfe --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/LogAdminServlet.java @@ -0,0 +1,2491 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class LogAdminServlet extends AdminServlet { + + 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 toHashtable(HttpServletRequest req) { + Hashtable httpReqHash = new Hashtable(); + 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 { + 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 { + 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() + "<<<"); + 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(); + String insts = null; + Enumeration 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.add(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 + */ + 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 newImpl = null; + + try { + newImpl = 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 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.add(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 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.add(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. + ILogEventListener logInst = (ILogEventListener) + mSys.getLogInstance(id); + + mSys.getLogInsts().remove((Object) 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 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; + } + } + + private synchronized void getLogConfig(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 configParams = mSys.getLogDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.add(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('='); + + params.add(kv.substring(0, index), + kv.substring(index + 1)); + } + } + sendResponse(0, null, params, resp); + return; + } + + private synchronized void getLogInstConfig(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 configParams = logInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.add(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.add(kv.substring(0, index), + kv.substring(index + 1)); + } + } + + sendResponse(SUCCESS, null, params, resp); + return; + } + + /** + * 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); + String type = ""; + + // 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 oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.add("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = (String) oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + + saveParams.add(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 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 + (key.equals(Constants.PR_LOG_TYPE)) { + type = val; + } + + 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(); + 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 + + try { + if (false) { + newMgrInst.init(mSys, substore); + } + } 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); + + // don't commit in this case and cleanup the new substore. + 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, e.toString(getLocale(req)), null, + resp); + return; + } catch (Throwable 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, e.toString(), null, + resp); + return; + } + + // 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 configParams = mSys.getLogDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.add(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.add(kv, ""); + } else { + params.add(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 configParams = logInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.add(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.add(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); + + Enumeration keys = saveParams.getNames(); + + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + String value = saveParams.getValue(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; + } + + /** + * Signed Audit Check Log Expiration Time + * + * This method is called to extract the log expiration time. + * <P> + * + * @param req http servlet request + * @return a string containing the log expiration time + */ + private String auditCheckLogExpirationTime(HttpServletRequest req) { + // check to see if the log expiration time parameter was changed + String expirationTime = req.getParameter( + Constants.PR_LOG_EXPIRED_TIME); + + if (expirationTime == null) { + expirationTime = ""; + } + + expirationTime = expirationTime.trim(); + + return expirationTime; + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java new file mode 100644 index 000000000..abb9aa30a --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/OCSPAdminServlet.java @@ -0,0 +1,560 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.util.*; +import netscape.security.x509.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.apps.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class OCSPAdminServlet extends AdminServlet { + + 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); + + Enumeration 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_CRLEXT_IMPL_NAME)) + continue; + if (name.equals("RULENAME")) + continue; + String value = req.getParameter(name); + + params.add(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(mOCSP.PROP_DEF_STORE_ID); + IConfigStore SubStore = config.getSubStore(mOCSP.PROP_STORE); + Enumeration enumStores = SubStore.getSubStoreNames(); + + while (enumStores.hasMoreElements()) { + String storeName = (String) enumStores.nextElement(); + boolean storeEnabled = false; + + if (storeName.equals(defStore)) { + storeEnabled = true; + } + params.add(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.add(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.add(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 { + Enumeration enum1 = req.getParameterNames(); + boolean restart = false; + + 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; + // } 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 log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER, + level, "CAAdminServlet: " + msg); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java new file mode 100644 index 000000000..8a8b28636 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/PolicyAdminServlet.java @@ -0,0 +1,1160 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class PolicyAdminServlet extends AdminServlet { + 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); + + if (authority != null) + mAuthority = (IAuthority) CMS.getSubsystem(authority); + if (mAuthority != null) + if (mAuthority instanceof ICertificateAuthority) { + mProcessor = ((ICertificateAuthority) mAuthority).getPolicyProcessor(); + } else if (mAuthority instanceof IRegistrationAuthority) { + mProcessor = ((IRegistrationAuthority) mAuthority).getPolicyProcessor(); + } else if (mAuthority instanceof IKeyRecoveryAuthority) { + mProcessor = ((IKeyRecoveryAuthority) mAuthority).getPolicyProcessor(); + } 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.getPair(IPolicyRule.PROP_ENABLE) == null) { + nvps.add(IPolicyRule.PROP_ENABLE, "boolean;Enable this policy rule"); + } + if (nvps.getPair(PROP_PREDICATE) == null) { + nvps.add(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 policyImplNames = mProcessor.getPolicyImplsInfo(); + Enumeration 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 = (String) policyImplNames.nextElement(); + IPolicyRule impl = (IPolicyRule) + policyImpls.nextElement(); + String className = + impl.getClass().getName(); + String desc = impl.getDescription(); + + nvp.add(id, className + "," + desc); + } + sendResponse(SUCCESS, null, nvp, resp); + } + + public void listPolicyInstances(HttpServletRequest req, + HttpServletResponse resp) + throws ServletException, IOException { + Enumeration instancesInfo = mProcessor.getPolicyInstancesInfo(); + + if (instancesInfo == null) { + sendResponse(ERROR, INVALID_POLICY_INSTANCE_CONFIG, null, resp); + return; + } + + // Assemble name value pairs + NameValuePairs nvp = new NameValuePairs(); + String instName, rest; + + while (instancesInfo.hasMoreElements()) { + String info = (String) instancesInfo.nextElement(); + int i = info.indexOf(";"); + + nvp.add(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 v = mProcessor.getPolicyImplConfig(id); + + if (v == null) { + sendResponse(ERROR, INVALID_POLICY_IMPL_ID, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + for (Enumeration e = v.elements(); e.hasMoreElements();) { + String nv = (String) e.nextElement(); + int index = nv.indexOf("="); + + nvp.add(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 v = mProcessor.getPolicyInstanceConfig(id); + + if (v == null) { + sendResponse(ERROR, INVALID_POLICY_INST_ID, null, resp); + return; + } + NameValuePairs nvp = new NameValuePairs(); + + for (Enumeration e = v.elements(); e.hasMoreElements();) { + String nv = (String) e.nextElement(); + int index = nv.indexOf("="); + String name = nv.substring(0, index); + String value = nv.substring(index + 1); + + if (value == null) { + value = ""; + } + + nvp.add(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 ht = new Hashtable(); + 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 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 e = v.elements(); e.hasMoreElements();) { + String nv = (String) 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 ht = new Hashtable(); + 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 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 (Enumeration n = req.getParameterNames(); n.hasMoreElements();) { + String p = (String) n.nextElement(); + String l = (String) 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/pki/base/common/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java new file mode 100644 index 000000000..d99562860 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/ProfileAdminServlet.java @@ -0,0 +1,2686 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.registry.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileAdminServlet extends AdminServlet { + 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; + } + + private void addDefaultParams(Object ext_info, NameValuePairs nvps) { + + /* make sure policy rules have 'enable' and 'predicate' */ + + if (ext_info instanceof IPolicyRule) { + if (nvps.getPair(IPolicyRule.PROP_ENABLE) == null) { + nvps.add(IPolicyRule.PROP_ENABLE, "boolean;Enable this policy rule"); + } + if (nvps.getPair(PROP_PREDICATE) == null) { + nvps.add(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.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); + String scope = super.getParameter(req, Constants.OP_SCOPE); + + 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); + String scope = super.getParameter(req, Constants.OP_SCOPE); + + 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 impls = mRegistry.getIds("profile"); + NameValuePairs nvp = new NameValuePairs(); + + while (impls.hasMoreElements()) { + String id = (String) impls.nextElement(); + IPluginInfo info = mRegistry.getPluginInfo("profile", id); + + nvp.add(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(); + + IProfilePolicy policy = null; + + 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; + } + policy = 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; + } + + IProfileInput input = null; + Enumeration names = req.getParameterNames(); + NameValuePairs nvps = new NameValuePairs(); + + 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; + nvps.add(name, req.getParameter(name)); + } + + try { + input = 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; + } + + IProfileOutput output = null; + Enumeration names = req.getParameterNames(); + NameValuePairs nvps = new NameValuePairs(); + + 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; + nvps.add(name, req.getParameter(name)); + } + + try { + output = 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 = ""; + Enumeration 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("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 = ""; + Enumeration 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("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 = ""; + Enumeration 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(); + IConfigStore defConfig = def.getConfigStore(); + + Enumeration 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(); + IConfigStore conConfig = con.getConfigStore(); + + Enumeration 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 { + 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(); + IConfigStore defConfig = def.getConfigStore(); + + Enumeration 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(); + + Enumeration 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(); + + Enumeration 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(); + IConfigStore conConfig = con.getConfigStore(); + + Enumeration 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."); + 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; + } + } + + 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 names = rule.getConfigNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + IDescriptor desc = rule.getConfigDescriptor(getLocale(req), name); + + if (desc == null) { + nvp.add(name, ";" + ";" + rule.getConfig(name)); + } else { + nvp.add(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 names = rule.getConfigNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + IDescriptor desc = rule.getConfigDescriptor(getLocale(req), name); + + if (desc == null) { + nvp.add(name, ";" + rule.getConfig(name)); + } else { + nvp.add(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 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 policies = profile.getProfilePolicies(setId); + + while (policies.hasMoreElements()) { + IProfilePolicy policy = (IProfilePolicy) policies.nextElement(); + IPolicyDefault def = policy.getDefault(); + IConfigStore defConfig = def.getConfigStore(); + IPolicyConstraint con = policy.getConstraint(); + IConfigStore conConfig = con.getConfigStore(); + + nvp.add(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 outputs = profile.getProfileOutputIds(); + + while (outputs.hasMoreElements()) { + String outputId = (String) outputs.nextElement(); + IProfileOutput output = profile.getProfileOutput(outputId); + + nvp.add(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 inputs = profile.getProfileInputIds(); + + while (inputs.hasMoreElements()) { + String inputId = (String) inputs.nextElement(); + IProfileInput input = profile.getProfileInput(inputId); + + nvp.add(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 names = profileInput.getConfigNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + IDescriptor desc = profileInput.getConfigDescriptor( + getLocale(req), name); + if (desc == null) { + nvp.add(name, ";" + ";" + profileInput.getConfig(name)); + } else { + nvp.add(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 names = profileOutput.getConfigNames(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + IDescriptor desc = profileOutput.getConfigDescriptor( + getLocale(req), name); + if (desc == null) { + nvp.add(name, ";" + ";" + profileOutput.getConfig(name)); + } else { + nvp.add(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 e = mProfileSub.getProfileIds(); + + while (e.hasMoreElements()) { + String profileId = (String) e.nextElement(); + IProfile profile = null; + + try { + profile = mProfileSub.getProfile(profileId); + } catch (EBaseException e1) { + // error + } + + String status = null; + + if (mProfileSub.isProfileEnable(profileId)) { + status = "enabled"; + } else { + status = "disabled"; + } + + // mInstanceId + ";visible;" + enabled + nvp.add(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.add("name", profile.getName(getLocale(req))); + nvp.add("desc", profile.getDescription(getLocale(req))); + nvp.add("visible", Boolean.toString(profile.isVisible())); + nvp.add("enable", Boolean.toString( + mProfileSub.isProfileEnable(id))); + + String authid = profile.getAuthenticatorId(); + + if (authid == null) { + nvp.add("auth", ""); + } else { + nvp.add("auth", authid); + } + CMS.debug("ProfileAdminServlet: authid=" + authid); + nvp.add("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 desc = req.getParameter("desc"); + 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/pki/base/common/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java new file mode 100644 index 000000000..c8d3555d9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/PublisherAdminServlet.java @@ -0,0 +1,2803 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.util.*; +import netscape.ldap.*; +import org.mozilla.jss.ssl.*; +import netscape.security.x509.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; + + +/** + * A class representing an publishing servlet for the + * Publishing subsystem. This servlet is responsible + * to serve configuration requests for the Publishing subsystem. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class PublisherAdminServlet extends AdminServlet { + 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 mappers = p.getMapperInsts().keys(); + Enumeration publishers = p.getPublisherInsts().keys(); + + StringBuffer map = new StringBuffer(); + + for (; mappers.hasMoreElements();) { + String name = (String) 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; + Plugin plugin = (Plugin) p_processor.getRulePlugins().get(implName); + + // 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); + + Enumeration 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_ENABLE)) + continue; + if (name.equals(Constants.PR_PUBLISHING_ENABLE)) + continue; + if (name.equals(Constants.PR_CERT_NAMES)) { + ICryptoSubsystem jss = (ICryptoSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_CRYPTO); + + params.add(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.add(name, value); + } + } + params.add(Constants.PR_PUBLISHING_ENABLE, + publishcfg.getString(IPublisherProcessor.PROP_ENABLE, Constants.FALSE)); + params.add(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 { + NameValuePairs params = new NameValuePairs(); + + //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 + Enumeration e = req.getParameterNames(); + String pwd = null; + + 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_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; + } + + /* 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" */ + if (pwd != null) + CMS.putPasswordCache(PW_TAG_CA_LDAP_PUBLISHING, pwd); + + try { + mProcessor.shutdown(); + mProcessor.startup(); + } 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 + Enumeration e = req.getParameterNames(); + String pwd = null; + + 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_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; + } + + /* 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.add("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.add(Constants.PR_CONN_INITED, + "Create ssl LDAPConnection with certificate: " + + certNickName + dashes(70 - 44 - certNickName.length()) + " Success"); + } catch (Exception ex) { + params.add(Constants.PR_CONN_INIT_FAIL, + "Create ssl LDAPConnection with certificate: " + + certNickName + dashes(70 - 44 - certNickName.length()) + " failure\n" + " exception: " + ex); + params.add(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.add(Constants.PR_CONN_OK, + "Connect to directory server " + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + " Success"); + params.add(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.add(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.add(Constants.PR_CONN_FAIL, + "Connect to directory server " + + host + " at port " + port + + dashes(70 - 37 - host.length() - (Integer.valueOf(port)).toString().length()) + + " Failure"); + } + params.add(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.add(Constants.PR_CONN_INITED, + "Create ssl LDAPConnection" + + dashes(70 - 25) + " Success"); + } else { + conn = new LDAPConnection(); + params.add(Constants.PR_CONN_INITED, + "Create LDAPConnection" + + dashes(70 - 21) + " Success"); + } + } catch (Exception ex) { + params.add(Constants.PR_CONN_INIT_FAIL, + "Create LDAPConnection" + + dashes(70 - 21) + " Failure\n" + + "exception: " + ex); + params.add(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.add(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.add(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.add(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.add(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.add(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.add(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.add(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.add(Constants.PR_AUTH_FAIL, + "Authentication: Basic authentication" + + dashes(70 - 36) + " Failure" + + "\nBind to the directory as: " + bindAs + + dashes(70 - 26 - bindAs.length()) + + " Failure"); + } + params.add(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" */ + CMS.putPasswordCache(PW_TAG_CA_LDAP_PUBLISHING, pwd); + // what a hack to do this without require restart server + ILdapAuthInfo authInfo = CMS.getLdapAuthInfo(); + + authInfo.addPassword(PW_TAG_CA_LDAP_PUBLISHING, pwd); + } + //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.add("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.add("publishCA", + "Failed to publish CA certificate."); + int index = ex.toString().indexOf("Failed to create CA"); + + if (index > -1) { + params.add("createError", + ex.toString().substring(index)); + } + mProcessor.shutdown(); + // Do you want to enable LDAP publishing anyway + params.add(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.add("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.add("publishCRL", + "Failed to publish CRL."); + mProcessor.shutdown(); + // Do you want to enable LDAP publishing anyway + params.add(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.add(Constants.PR_SAVE_OK, + "\n \nConfiguration changes are now committed."); + params.add("restarted", "Publishing is restarted."); + } else { + commit(true); + params.add(Constants.PR_SAVE_OK, + "\n \nConfiguration changes are now committed."); + params.add("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 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.add(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 e = mProcessor.getMapperPlugins().keys(); + + while (e.hasMoreElements()) { + String name = (String) 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.add(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 e = mProcessor.getMapperInsts().keys(); + + for (; e.hasMoreElements();) { + String name = (String) e.nextElement(); + ILdapMapper value = mProcessor.getMapperInstance(name); + + params.add(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. + ILdapMapper mapperInst = (ILdapMapper) + mProcessor.getMapperInstance(id); + + mProcessor.getMapperInsts().remove((Object) 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 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 configParams = mProcessor.getMapperDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.add(Constants.PR_MAPPER_IMPL_NAME, ""); + if (configParams != null) { + for (int i = 0; i < configParams.size(); i++) { + String kv = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + params.add(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 configParams = mapperInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.add(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 = (String) configParams.elementAt(i); + int index = kv.indexOf('='); + + params.add(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 oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.add("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = (String) oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + + saveParams.add(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 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 = (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); + } + } + } + + // 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 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 = (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 { + 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.add(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 e = mProcessor.getRulePlugins().keys(); + + while (e.hasMoreElements()) { + String name = (String) 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.add(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(); + String insts = null; + Enumeration e = mProcessor.getRuleInsts().keys(); + + for (; e.hasMoreElements();) { + String name = (String) e.nextElement(); + ILdapRule value = (ILdapRule) + mProcessor.getRuleInsts().get((Object) name); + String enabled = value.enabled() ? "enabled" : "disabled"; + + params.add(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 e = mProcessor.getRuleInsts().elements(); + e.hasMoreElements();) { + ILdapRule rule = (ILdapRule) + 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. + ILdapRule ruleInst = (ILdapRule) + mProcessor.getRuleInsts().get(id); + + mProcessor.getRuleInsts().remove((Object) 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 configParams = mProcessor.getRuleDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.add(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.add(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 configParams = ruleInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.add(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.add(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 oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.add("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = (String) oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + + saveParams.add(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 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 = (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, + 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 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 = (String) 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.add(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 e = mProcessor.getPublisherPlugins().keys(); + + while (e.hasMoreElements()) { + String name = (String) 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.add(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(); + String insts = null; + Enumeration e = mProcessor.getPublisherInsts().keys(); + + for (; e.hasMoreElements();) { + String name = (String) e.nextElement(); + ILdapPublisher value = mProcessor.getPublisherInstance(name); + + if (value == null) + continue; + params.add(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 e = mProcessor.getPublisherInsts().keys(); + e.hasMoreElements();) { + String name = (String) 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. + ILdapPublisher publisherInst = mProcessor.getPublisherInstance(id); + + mProcessor.getPublisherInsts().remove((Object) 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 configParams = mProcessor.getPublisherDefaultParams(implname); + NameValuePairs params = new NameValuePairs(); + + // implName is always required so always send it. + params.add(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.add(kv, ""); + } else { + params.add(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 configParams = publisherInst.getInstanceParams(); + NameValuePairs params = new NameValuePairs(); + + params.add(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.add(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 oldConfigParms = oldinst.getInstanceParams(); + NameValuePairs saveParams = new NameValuePairs(); + + // implName is always required so always include it it. + saveParams.add("pluginName", implname); + if (oldConfigParms != null) { + for (int i = 0; i < oldConfigParms.size(); i++) { + String kv = (String) oldConfigParms.elementAt(i); + int index = kv.indexOf('='); + + saveParams.add(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"); + + // create new substore. + + Vector 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); + } + } + } + + // 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 routine. + private static void restore(IConfigStore store, + String id, NameValuePairs saveParams) { + store.removeSubStore(id); + IConfigStore rstore = store.makeSubStore(id); + + Enumeration keys = saveParams.getNames(); + + while (keys.hasMoreElements()) { + String key = (String) keys.nextElement(); + String value = saveParams.getValue(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/pki/base/common/src/com/netscape/cms/servlet/admin/RAAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/RAAdminServlet.java new file mode 100644 index 000000000..be3617b21 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/RAAdminServlet.java @@ -0,0 +1,576 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.util.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.policy.*; +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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class RAAdminServlet extends AdminServlet { + 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(); + Enumeration 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_ENABLE)) + continue; + params.add(name, rc.getString(name, "")); + } + + params.add(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(mRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(mRA.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(mRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(mRA.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(mRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(mRA.PROP_REQ_IN_Q_SUBSTORE); + + Enumeration 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_ENABLE)) + continue; + params.add(name, riq.getString(name, "")); + } + + params.add(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(mRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore riq = nc.getSubStore(mRA.PROP_REQ_IN_Q_SUBSTORE); + + //set rest of the parameters + Enumeration 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_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 + Enumeration 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_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(mRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(mRA.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(mRA.PROP_NOTIFY_SUBSTORE); + + IConfigStore rc = nc.getSubStore(mRA.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")) + } + } + */ + + Enumeration enum1 = req.getParameterNames(); + NameValuePairs params = new NameValuePairs(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = (String) enum1.nextElement(); + + if (name.equals(Constants.RS_ID)) + continue; + if (name.equals(Constants.OP_SCOPE)) + continue; + if (name.equals(Constants.OP_TYPE)) + continue; + + params.add(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"); + } + + Enumeration enum1 = req.getParameterNames(); + + if (caConnectorConfig != null) { + while (enum1.hasMoreElements()) { + String name = (String) 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) { + + Enumeration enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) 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) { + + Enumeration enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) 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) { + + Enumeration enum1 = req.getParameterNames(); + + while (enum1.hasMoreElements()) { + String key = (String) 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/pki/base/common/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java new file mode 100644 index 000000000..ac1049951 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/RegistryAdminServlet.java @@ -0,0 +1,358 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.registry.*; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.ra.IRegistrationAuthority; +import com.netscape.certsrv.kra.IKeyRecoveryAuthority; +import com.netscape.certsrv.profile.*; + +/** + * This implements the administration servlet for registry subsystem. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class RegistryAdminServlet extends AdminServlet { + 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); + String scope = req.getParameter(Constants.OP_SCOPE); + + 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)) { + deleteImpl(req, resp); + } else if (op.equals(OpDef.OP_ADD)) { + 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 impls = mRegistry.getIds(scope); + NameValuePairs nvp = new NameValuePairs(); + + while (impls.hasMoreElements()) { + String id = (String) impls.nextElement(); + IPluginInfo info = mRegistry.getPluginInfo(scope, id); + + nvp.add(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 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.add(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 names = template.getConfigNames(); + + if (names != null) { + while (names.hasMoreElements()) { + String name = (String) 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.add(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/pki/base/common/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java b/pki/base/common/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java new file mode 100644 index 000000000..f929587b4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/admin/UsrGrpAdminServlet.java @@ -0,0 +1,2296 @@ +// --- 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.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.InternalCertificate; +import com.netscape.cmsutil.util.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.password.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.base.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class UsrGrpAdminServlet extends AdminServlet { + + 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 IAuthzSubsystem mAuthz = null; + + /** + * 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.add(Constants.PR_USER_TYPE, val); + sendResponse(SUCCESS, null, params, resp); + } + + /** + * Retrieves configuration parameters of + * authentication manager. + */ + private synchronized void getConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + super.getConfig(mMgr.getConfigStore(), req, resp); + } + + /** + * Sets configuration parameters of + * User/Group manager. + */ + private synchronized void setConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + super.setConfig(mMgr.getConfigStore(), req, resp); + } + + /** + * Lists configuration parameters. + */ + private synchronized void listConfig(HttpServletRequest req, + HttpServletResponse resp) throws ServletException, + IOException, EBaseException { + super.listConfig(mMgr.getConfigStore(), req, 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 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 = (IUser) 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.add("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.add(Constants.PR_USER_FULLNAME, user.getFullName()); + params.add(Constants.PR_USER_EMAIL, user.getEmail()); + params.add(Constants.PR_USER_PHONE, user.getPhone()); + params.add(Constants.PR_USER_STATE, user.getState()); + + // get list of groups, and get a list of those that this + // uid belongs to + Enumeration 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 = (IGroup) e.nextElement(); + + if (group.isMember(id) == true) { + if (grpString.length()!=0) { + grpString.append(","); + } + grpString.append(group.getGroupID()); + } + } + + params.add(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.add(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 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 = (IGroup) e.nextElement(); + String desc = group.getDescription(); + + if (desc != null) { + params.add(group.getGroupID(), desc); + } else { + params.add(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 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 = (IGroup) e.nextElement(); + + params.add(Constants.PR_GROUP_GROUP, group.getGroupID()); + params.add(Constants.PR_GROUP_DESC, + group.getDescription()); + + Enumeration members = group.getMemberNames(); + StringBuffer membersString = new StringBuffer(); + + if (members != null) { + while (members.hasMoreElements()) { + if (membersString.length()!=0) { + membersString.append(", "); + } + + String mn = (String) members.nextElement(); + + membersString.append(mn); + } + } + + params.add(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 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 = (IGroup) 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) { + String errMsg = "addUser()" + e.toString(); + + 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[] = (byte[]) (com.netscape.osutil.OSUtil.AtoB(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[] = (byte[]) (com.netscape.osutil.OSUtil.AtoB(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 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(Constants.PR_MULTIROLES); + } catch (Exception eee) { + } + while (st.hasMoreTokens()) { + String memberName = st.nextToken(); + + if (multiRole) { + group.addMemberName(memberName); + } else { + if (groupName.equals("Administrators") || + groupName.equals("Auditors") || + groupName.equals("Trusted Managers") || + groupName.equals("Certificate Manager Agents") || + groupName.equals("Registration Manager Agents") || + groupName.equals("Data Recovery Manager Agents") || + groupName.equals("Online Certificate Status Manager Agents")) { + 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 isDuplicate(String groupName, String memberName) { + Enumeration groups = null; + + try { + groups = mMgr.listGroups("*"); + while (groups.hasMoreElements()) { + IGroup group = (IGroup) groups.nextElement(); + String name = group.getName(); + Enumeration g = mMgr.findGroups(name); + IGroup g1 = (IGroup) g.nextElement(); + + if (!name.equals(groupName)) { + if (name.equals("Administrators") || + name.equals("Auditors") || + name.equals("Trusted Managers") || + name.equals("Certificate Manager Agents") || + name.equals("Registration Manager Agents") || + name.equals("Data Recovery Manager Agents") || + name.equals("Online Certificate Status Manager Agents")) { + Enumeration members = g1.getMemberNames(); + + while (members.hasMoreElements()) { + String m1 = (String) 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); + } + + 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/pki/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java new file mode 100644 index 000000000..0c1cf2f97 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/CMSServlet.java @@ -0,0 +1,2101 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cmsutil.xml.*; +import com.netscape.certsrv.base.SessionContext; +import java.io.*; +import java.util.*; +import java.util.Locale; +import java.util.Enumeration; +import java.util.Vector; +import java.util.Hashtable; +import java.util.StringTokenizer; +import java.util.Date; +import java.math.BigInteger; + +import java.security.cert.X509Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletException; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; + +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.RevokedCertImpl; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.CRLReasonExtension; +import netscape.security.x509.CRLExtensions; +import netscape.security.pkcs.PKCS7; +import netscape.security.pkcs.ContentInfo; +import netscape.security.pkcs.SignerInfo; +import netscape.security.util.DerValue; +import netscape.security.util.DerOutputStream; +import netscape.security.util.ObjectIdentifier; + +import org.mozilla.jss.ssl.SSLSocket; +import org.mozilla.jss.ssl.SSLSecurityStatus; +import org.w3c.dom.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authorization.*; + +import com.netscape.certsrv.authentication.*; + +import com.netscape.certsrv.dbs.certdb.*; + +import com.netscape.certsrv.logging.ILogger; + +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.IRequest; + +import java.security.NoSuchAlgorithmException; +import java.security.MessageDigest; +import java.net.SocketException; + + +/** + * This is the base class of all CS servlet. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public abstract class CMSServlet extends HttpServlet { + // 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 mTemplates = new Hashtable(); + + protected ServletConfig mServletConfig = null; + protected ServletContext mServletContext = null; + private CMSFileLoader mFileLoader = null; + + protected Vector mDontSaveHttpParams = new Vector(); + protected Vector mSaveHttpHeaders = new Vector(); + + 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 toHashtable(HttpServletRequest req) { + Hashtable httpReqHash = new Hashtable(); + 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 = Utils.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 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 hided, + // all sensitive parameters should be prefixed with + // __ (double underscores) + if (pn.startsWith("__")) { + 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) { + } + + if (CMS.debugOn()) { + outputHttpParameters(httpReq); + } + CMS.debug("CMSServlet: " + mId + " start to service."); + String className = this.getClass().getName(); + + // 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((Object) cmsRequest, (Object) 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(PrintStream ps, String name, + IArgBlock argBlock) + { + ps.println("<" + name + ">"); + if (argBlock != null) { + Enumeration names = argBlock.getElements(); + while (names.hasMoreElements()) { + String n = (String) names.nextElement(); + ps.println("<" + n + ">"); + String val = argBlock.get(n).toString(); + val = val.trim(); + ps.println((val != null)? val:""); + ps.println("</" + n + ">"); + } + } + ps.println("</" + name + ">"); + } + + protected void outputAsXML(ByteArrayOutputStream bos, CMSTemplateParams params) + { + PrintStream ps = new PrintStream(bos); + ps.println("<xml>"); + outputArgBlockAsXML(ps, "header", params.getHeader()); + outputArgBlockAsXML(ps, "fixed", params.getFixed()); + ps.println("</xml>"); + ps.flush(); + } + + protected void outputXML(HttpServletResponse resp, CMSTemplateParams params) + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + resp.setContentType("text/xml"); + outputAsXML(bos, params); + resp.setContentLength(bos.size()); + try { + bos.writeTo(resp.getOutputStream()); + } 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; + + 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])); + } + 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) { + SSLSocket s = null; + + /* + 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 headers = new Hashtable(); + Enumeration hdrs = mSaveHttpHeaders.elements(); + + while (hdrs.hasMoreElements()) { + String hdr = (String) 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 saveParams = new Hashtable(); + + Enumeration names = httpParams.elements(); + + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + Enumeration params = mDontSaveHttpParams.elements(); + boolean dosave = true; + + while (params.hasMoreElements()) { + String param = (String) 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, 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 = + (ICertificateRepository) ((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 = + (ICertificateRepository) ((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 e = token.getElements(); + while (e.hasMoreElements()) { + String n = (String) 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 = com.netscape.osutil.OSUtil.BtoA(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); + + 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, IAuthToken authToken, + String exp) throws EBaseException { + AuthzToken authzToken = mAuthz.authorize(authzMgrName, authToken, + exp); + return authzToken; + } + + /** + * 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 auditACLResource = resource; + String auditOperation = operation; + + // "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, + auditSubjectID, + 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, + auditSubjectID, + 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, + auditSubjectID, + 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; + } + + 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 Groups + * + * This method is called to extract all "groups" associated + * with the "auditSubjectID()". + * <P> + * + * @param id 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 groups = null; + + try { + groups = mUG.findGroups("*"); + } catch (Exception e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + StringBuffer membersString = new StringBuffer(); + + while (groups.hasMoreElements()) { + IGroup group = (IGroup) 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); + } + + protected void outputError(HttpServletResponse httpResp, String status, String errorString) { + XMLObject xmlObj = null; + try { + xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + xmlObj.addItemToContainer(root, "Status", status); + xmlObj.addItemToContainer(root, "Error", errorString); + 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())); + } + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/base/CMSStartServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/CMSStartServlet.java new file mode 100644 index 000000000..efb84e3fe --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/CMSStartServlet.java @@ -0,0 +1,104 @@ +// --- 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 com.netscape.cms.servlet.common.*; + +import java.io.*; + +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; + + +/** + * This servlet is started by the web server at startup, and + * it starts the CMS framework. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CMSStartServlet extends HttpServlet { + 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()) { + boolean success = f1.renameTo(f); + if (!success) { + String cmds[] = new String[3]; + if (File.separator.equals("\\")) { + cmds[0] = "cmd"; + cmds[1] = "/c"; + cmds[2] = "copy "+ + f1.getAbsolutePath().replace('/', '\\') + " " + + f.getAbsolutePath().replace('/', '\\'); + } else { + cmds[0] = "/bin/sh"; + cmds[1] = "-c"; + cmds[2] = "cp " + f1.getAbsolutePath() + " " + + f.getAbsolutePath(); + } + + try { + Process process = Runtime.getRuntime().exec(cmds); + process.waitFor(); + } 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/pki/base/common/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.java new file mode 100644 index 000000000..09cc21a1e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/DisplayHtmlServlet.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.base; + + +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cms.servlet.common.*; + + +/** + * This is the servlet that displays the html page for the corresponding input id. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisplayHtmlServlet extends CMSServlet { + 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 "); + + IAuthToken authToken = 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/pki/base/common/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.java new file mode 100644 index 000000000..c13720c48 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/DynamicVariablesServlet.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.base; + + +import com.netscape.cms.servlet.common.*; +import java.io.*; +import java.util.*; +import java.lang.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.dbs.*; +import org.mozilla.jss.ssl.SSLSocket; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DynamicVariablesServlet extends CMSServlet { + 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 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(); + + 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, (Object) 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 { + IAuthToken token = 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 k = dynvars.keys(); + + while (k.hasMoreElements()) { + String toBeWritten; + Integer varcode = (Integer) 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 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 = (IAuthManager) 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/pki/base/common/src/com/netscape/cms/servlet/base/GetStats.java b/pki/base/common/src/com/netscape/cms/servlet/base/GetStats.java new file mode 100644 index 000000000..608415edf --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/GetStats.java @@ -0,0 +1,177 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.util.*; + + +/** + * Retrieve information. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetStats extends CMSServlet { + 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; + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + 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 names = st.getSubEventNames(); + while (names.hasMoreElements()) { + String name = (String)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/pki/base/common/src/com/netscape/cms/servlet/base/IndexServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/IndexServlet.java new file mode 100644 index 000000000..e855ec7ea --- /dev/null +++ b/pki/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 com.netscape.cms.servlet.common.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.CMS; + + +/** + * This is the servlet that builds the index page in + * various ports. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class IndexServlet extends CMSServlet { + 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/pki/base/common/src/com/netscape/cms/servlet/base/PortsServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/PortsServlet.java new file mode 100644 index 000000000..270498baf --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/PortsServlet.java @@ -0,0 +1,93 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import java.net.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.http.*; +import org.xml.sax.*; +import org.w3c.dom.*; + +/** + * This servlet returns port information. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class PortsServlet extends CMSServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/base/ProxyServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/ProxyServlet.java new file mode 100644 index 000000000..7200235a1 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/ProxyServlet.java @@ -0,0 +1,246 @@ +/* CMS_SDK_LICENSE_TEXT */ + +package com.netscape.cms.servlet.base; + + +import com.netscape.cms.servlet.common.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.kra.*; +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: 3765 $, $Date: 2002-12-13 14:15:08 -0800 (Fri, 13 Dec 2002) $ + */ +public class ProxyServlet extends HttpServlet { + + private String mDest = null; + private String mDestContext = null; + private String mSrcContext = null; + private String mAppendPathInfo = null; + private Vector mMatchStrings = new Vector(); + private String mDestServletOnNoMatch = null; + private String mAppendPathInfoOnNoMatch = null; + private Map mParamMap = new HashMap(); + private Map mParamValue = new HashMap(); + + 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 = (String)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 mMap = null; + private Map mValueMap = null; + + public ProxyWrapper(HttpServletRequest req) + { + super(req); + } + + public void setParameterMapAndValue(Map m,Map v) + { + if (m != null) mMap = m; + if (v != null) mValueMap = v; + } + + public Map 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 n = new HashMap(); + // get the HTTP parameters the user supplied. + Map m = super.getParameterMap(); + Set s = m.entrySet(); + Iterator i = s.iterator(); + while (i.hasNext()) { + Map.Entry me = (Map.Entry) i.next(); + String name = (String) me.getKey(); + String[] values = (String[])(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 s2 = mValueMap.entrySet(); + Iterator i2 = s2.iterator(); + // Cycle through all the static values + while (i2.hasNext()) { + Map.Entry me2 = (Map.Entry) i2.next(); + String name2 = (String) me2.getKey(); + if (n.get(name2) == null) { + String[] values2 = (String[])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/pki/base/common/src/com/netscape/cms/servlet/base/SystemInfoServlet.java b/pki/base/common/src/com/netscape/cms/servlet/base/SystemInfoServlet.java new file mode 100644 index 000000000..a751f40b7 --- /dev/null +++ b/pki/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 com.netscape.cms.servlet.common.*; + +import java.util.*; +import java.io.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.request.*; + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class SystemInfoServlet extends HttpServlet { + + 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 { + boolean collect = false; + 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/pki/base/common/src/com/netscape/cms/servlet/base/UserInfo.java b/pki/base/common/src/com/netscape/cms/servlet/base/UserInfo.java new file mode 100644 index 000000000..2abcc6aae --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/base/UserInfo.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) 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java b/pki/base/common/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java new file mode 100644 index 000000000..d89288006 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/CMCRevReqServlet.java @@ -0,0 +1,1141 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.util.Locale; +import java.io.IOException; +import java.math.BigInteger; + +import java.security.cert.X509Certificate; +import java.security.cert.CertificateException; + +import netscape.security.x509.*; + + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; + +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.request.*; + +import com.netscape.certsrv.dbs.certdb.*; + +import com.netscape.certsrv.authentication.*; + +import com.netscape.certsrv.logging.*; + +import com.netscape.certsrv.publish.*; + + +/** + * Revoke a certificate with a CMC-formatted revocation request + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CMCRevReqServlet extends CMSServlet { + 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")); + } + EBaseException error = null; + + 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, "submit"); + } 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); + } + RevocationReason reason = RevocationReason.fromInt(reasonCode.intValue()); + + 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 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.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } + + /** + * 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; + } + + /** + * Revoke the specified certificate + */ + private BigInteger getCertFromAuthMgr( + AuthToken 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; + } + + /** + * get cert to revoke from ssl + */ + private BigInteger getCertFromSSL( + HttpServletRequest req, X509CertImpl[] certContainer) + throws EBaseException { + X509Certificate cert = getSSLClientCertificate(req); + + if (cert == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_MISSING_CERTS_REVOKE_FROM_SSL")); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_MISSING_CERTS_REVOKE_FROM_SSL")); + } + 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")); + } + BigInteger serialno = ((X509Certificate) cert).getSerialNumber(); + + certContainer[0] = (X509CertImpl) cert; + + return serialno; + } + + /** + * 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 oldCertsV = new Vector(); + Vector revCertImplsV = new Vector(); + + // 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 e = list.getCertRecords(0, totalRecordCount - 1); + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) 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 serialNumbers = new Vector(); + + 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 = com.netscape.osutil.OSUtil.AtoB(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.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 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 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/pki/base/common/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java b/pki/base/common/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java new file mode 100644 index 000000000..70f0f50f7 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/ChallengeRevocationServlet1.java @@ -0,0 +1,701 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.util.Locale; +import java.io.IOException; +import java.math.BigInteger; + +import java.security.cert.CertificateException; + +import netscape.security.x509.*; + + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.publish.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ChallengeRevocationServlet1 extends CMSServlet { + 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")); + } + + EBaseException error = null; + + 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); + RevocationReason reason = RevocationReason.fromInt(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 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.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 oldCertsV = new Vector(); + Vector revCertImplsV = new Vector(); + + // 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 e = list.getCertRecords(0, totalRecordCount - 1); + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) 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 serialNumbers = new Vector(); + + 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 = com.netscape.osutil.OSUtil.AtoB(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 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 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/pki/base/common/src/com/netscape/cms/servlet/cert/CloneRedirect.java b/pki/base/common/src/com/netscape/cms/servlet/cert/CloneRedirect.java new file mode 100644 index 000000000..96fade289 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/CloneRedirect.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.cert; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.authentication.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.apps.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CloneRedirect extends CMSServlet { + + 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(); + + 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_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(); + + 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.getLogMessage("CMSGW_ERROR_DISPLAY_TEMPLATE")); + } + } + + /** + * Display information about redirecting to the master's URL info + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + HttpServletRequest req, + HttpServletResponse resp, + String signatureAlgorithm, + Locale locale) + throws EBaseException { + + CMS.debug("CloneRedirect: " + CMS.getLogMessage("ADMIN_SRVLT_ADD_MASTER_URL", mNewUrl)); + header.addStringValue("masterURL", mNewUrl); + return; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/DirAuthServlet.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DirAuthServlet.java new file mode 100644 index 000000000..671f0f1dc --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DirAuthServlet.java @@ -0,0 +1,242 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.authentication.*; +import com.netscape.cms.servlet.*; + + +/** + * 'Face-to-face' certificate enrollment. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DirAuthServlet extends CMSServlet { + 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 { + IArgBlock httpParams = cmsReq.getHttpParams(); + 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/pki/base/common/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java new file mode 100644 index 000000000..a1aca5a8d --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DisableEnrollResult.java @@ -0,0 +1,172 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.authentication.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cms.servlet.*; + + +/** + * For Face-to-face enrollment, disable EE enrollment feature + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisableEnrollResult extends CMSServlet { + 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/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayBySerial.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayBySerial.java new file mode 100644 index 000000000..b51ec2cda --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayBySerial.java @@ -0,0 +1,462 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import netscape.security.extensions.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.extensions.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; + + +/** + * Display detailed information about a certificate + * + * The template 'displayBySerial.template' is used to + * render the response for this servlet. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisplayBySerial extends CMSServlet { + + 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); + ICertRecord rec = getCertRecord(serialNumber, certType); + + 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")); + } + + 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 { + ICertRecord rec = getCertRecord(seq, certType); + + 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 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", com.netscape.osutil.OSUtil.BtoA(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 = com.netscape.osutil.OSUtil.BtoA(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/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayCRL.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayCRL.java new file mode 100644 index 000000000..22f1f96ca --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayCRL.java @@ -0,0 +1,464 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.CRLException; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + +import com.netscape.cms.servlet.*; + + +/** + * Decode the CRL and display it to the requester. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisplayCRL extends CMSServlet { + + 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. + EBaseException error = null; + + String crlIssuingPointId = req.getParameter("crlIssuingPoint"); + + process(argSet, header, req, resp, crlIssuingPointId, + locale[0]); + + 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 CRL. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + HttpServletRequest req, + HttpServletResponse resp, + String crlIssuingPointId, + Locale locale) { + boolean updateStatus = true; + EBaseException error = null; + ICRLIssuingPoint crlIP = null; + X509CRLImpl crl = null; + boolean clonedCA = false; + String masterHost = null; + String masterPort = null; + Vector 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 = (String)ipNames.elementAt(i); + if (crlIssuingPointId.equals(ipName)) { + break; + } + } + if (i >= ipNames.size()) crlIssuingPointId = null; + } else { + crlIssuingPointId = null; + } + } + } else { + if (crlIssuingPointId != null) { + Enumeration ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = (ICRLIssuingPoint) ips.nextElement(); + + if (crlIssuingPointId.equals(ip.getId())) { + crlIP = ip; + 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 || 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 = com.netscape.osutil.OSUtil.BtoA(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 = com.netscape.osutil.OSUtil.BtoA(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 { + 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/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java new file mode 100644 index 000000000..0c24ae2c2 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DisplayHashUserEnroll.java @@ -0,0 +1,231 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.authentication.*; +import com.netscape.cms.servlet.*; + + +/** + * XXX Servlet to report the status, ie, the agent-initiated user + * enrollment is enabled or disabled. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisplayHashUserEnroll extends CMSServlet { + 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(); + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + 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 { + IArgBlock httpParams = cmsReq.getHttpParams(); + 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/pki/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java new file mode 100644 index 000000000..f0490adc8 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DoRevoke.java @@ -0,0 +1,1104 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.logging.*; + + +/** + * Revoke a Certificate + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DoRevoke extends CMSServlet { + + 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 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 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; + + 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; + + /* 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"); + 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) { + 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); + + long startTime = CMS.getCurrentDate().getTime(); + + try { + int count = 0; + Vector oldCertsV = new Vector(); + Vector revCertImplsV = new Vector(); + + // 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 e = mCertDB.searchCertificates(revokeAll, + totalRecordCount, mTimeLimits); + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) 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 serialNumbers = new Vector(); + + 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_ERROR_MARKING_CERT_REVOKED")); + } + + 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 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 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(); + + // 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/pki/base/common/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java new file mode 100644 index 000000000..edb34a32e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DoRevokeTPS.java @@ -0,0 +1,886 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.logging.*; + + +/** + * Revoke a Certificate + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DoRevokeTPS extends CMSServlet { + + 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; + CMSTemplate form = null; + Locale[] locale = new Locale[1]; + + CMS.debug("DoRevokeTPS before getTemplate"); + 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")); + } 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 { + ServletOutputStream out = resp.getOutputStream(); + + 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); + + long startTime = CMS.getCurrentDate().getTime(); + + try { + int count = 0; + Vector oldCertsV = new Vector(); + Vector revCertImplsV = new Vector(); + + // 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 e = mCertDB.searchCertificates(revokeAll, + totalRecordCount, mTimeLimits); + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) 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("DoRevokeTPS: skipped revocation request for system certificate " + xcert.getSerialNumber()); + continue; + } + + if (xcert != null) { + rarg.addStringValue("serialNumber", + xcert.getSerialNumber().toString(16)); + + if (rec.getStatus().equals(ICertRecord.STATUS_REVOKED)) { + 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++; + } + } + } + + if (count == 0) { + 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 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"); + 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++; + } + } + } + + // 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 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" + + 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/pki/base/common/src/com/netscape/cms/servlet/cert/DoUnrevoke.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DoUnrevoke.java new file mode 100644 index 000000000..56266010a --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DoUnrevoke.java @@ -0,0 +1,659 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.lang.*; +import java.math.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.logging.*; + + +/** + * 'Unrevoke' a certificate. (For certificates that are on-hold only, + * take them off-hold) + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DoUnrevoke extends CMSServlet { + + 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 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 = 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 biList = new Vector(); + 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" + + Integer.toHexString( + Integer.valueOf(serialNumber).intValue()); + } else { + serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + return serialNumber; + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java b/pki/base/common/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java new file mode 100644 index 000000000..c4cd57034 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/DoUnrevokeTPS.java @@ -0,0 +1,613 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.lang.*; +import java.math.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.logging.*; + + +/** + * 'Unrevoke' a certificate. (For certificates that are on-hold only, + * take them off-hold) + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DoUnrevokeTPS extends CMSServlet { + + 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; + + 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 { + 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 { + ServletOutputStream out = resp.getOutputStream(); + + 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 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 = 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 biList = new Vector(); + 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" + + Integer.toHexString( + Integer.valueOf(serialNumber).intValue()); + } else { + serialNumber = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + return serialNumber; + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java b/pki/base/common/src/com/netscape/cms/servlet/cert/EnableEnrollResult.java new file mode 100644 index 000000000..9ccb6c974 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/EnableEnrollResult.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.cert; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.authentication.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cms.servlet.*; + + +/** + * XXX see disable + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class EnableEnrollResult extends CMSServlet { + 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/pki/base/common/src/com/netscape/cms/servlet/cert/EnrollServlet.java b/pki/base/common/src/com/netscape/cms/servlet/cert/EnrollServlet.java new file mode 100644 index 000000000..32a524023 --- /dev/null +++ b/pki/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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; + +import java.io.*; + +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; + + +import netscape.security.x509.*; +import netscape.security.pkcs.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +import com.netscape.cms.servlet.processors.PKIProcessor; +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.certsrv.apps.*; +import com.netscape.certsrv.base.*; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; + +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; + +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import java.math.*; + + +/** + * Submit a Certificate Enrollment request + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class EnrollServlet extends CMSServlet { + 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!"); + + // 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 en = list.getCertRecords(0, size - 1); + boolean gotEncCert = false; + + 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 = (ICertRecord) 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 messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration 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}; + + X509CertInfo authCertInfo = null; + 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; + + String certType = null; + + // + String test = httpParams.getValueAsString("certNickname", null); + + // support Enterprise 3.5.1 server where CERT_TYPE=csrCertType + // instead of certType + 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); + } + + 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; + } + } + + } + + /** + * 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 = com.netscape.osutil.OSUtil.BtoA(rawData).trim(); + + StringBuffer sb = new StringBuffer(); + // extract all line separators from the "base64Data" + for (int i = 0; i < base64Data.length(); i++) { + if (base64Data.substring(i, i).getBytes() != EOL) { + sb.append(base64Data.substring(i, i)); + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/GetBySerial.java b/pki/base/common/src/com/netscape/cms/servlet/cert/GetBySerial.java new file mode 100644 index 000000000..bd001672c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/GetBySerial.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.cert; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import java.security.cert.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cmsutil.crypto.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.pkix.crmf.*; + + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Retrieve certificate by serial number. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetBySerial extends CMSServlet { + + 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 { + int serialNumber = -1; + boolean noError = true; + + 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("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("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(); + + String browser1 = req.getParameter("browser"); + 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/pki/base/common/src/com/netscape/cms/servlet/cert/GetCAChain.java b/pki/base/common/src/com/netscape/cms/servlet/cert/GetCAChain.java new file mode 100644 index 000000000..3dec251b8 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/GetCAChain.java @@ -0,0 +1,400 @@ +// --- 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 com.netscape.cms.servlet.common.*; + import com.netscape.cms.servlet.base.*; + import java.io.*; + import java.util.*; + import java.math.*; + import javax.servlet.*; + import java.security.cert.*; + import javax.servlet.http.*; + import netscape.ldap.*; + import netscape.security.x509.*; + import com.netscape.certsrv.base.*; + import com.netscape.certsrv.authority.*; + import com.netscape.certsrv.policy.*; + import com.netscape.certsrv.request.IRequest; + import com.netscape.certsrv.dbs.*; + import com.netscape.certsrv.dbs.certdb.*; + import com.netscape.certsrv.ldap.*; + import com.netscape.certsrv.logging.*; + import com.netscape.certsrv.apps.CMS; + import com.netscape.certsrv.authentication.*; + import com.netscape.certsrv.authorization.*; + import com.netscape.cms.servlet.*; + + + /** + * Retrieve the Certificates comprising the CA Chain for this CA. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ + public class GetCAChain extends CMSServlet { + 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")) { + 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 (clientIsMSIE(httpReq)) { + if (op.equals("downloadBIN")) { + httpResp.setHeader("Content-disposition", + "attachment; filename=getCAChain.cacert"); + } + } + 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 { + String outputString = null; + + 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; + } + + /** + * gets base 64 encoded cert chain + */ + private String getChainBase64(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/pki/base/common/src/com/netscape/cms/servlet/cert/GetCRL.java b/pki/base/common/src/com/netscape/cms/servlet/cert/GetCRL.java new file mode 100644 index 000000000..cea61e65c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/GetCRL.java @@ -0,0 +1,457 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; + + +/** + * Retrieve CRL for a Certificate Authority + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetCRL extends CMSServlet { + 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); + } + + 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 (crl == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSGW_FAILED_DECODE_CRL")); + 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 = com.netscape.osutil.OSUtil.BtoA(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 = com.netscape.osutil.OSUtil.BtoA(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/pki/base/common/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java b/pki/base/common/src/com/netscape/cms/servlet/cert/GetCertFromRequest.java new file mode 100644 index 000000000..6fdfe380d --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/GetCertFromRequest.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.cert; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.extensions.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import netscape.security.extensions.*; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.Extension; +import netscape.security.x509.KeyUsageExtension; +import javax.servlet.*; +import javax.servlet.http.*; +import java.io.*; +import java.util.Locale; +import com.netscape.certsrv.apps.*; + + +/** + * Gets a issued certificate from a request id. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetCertFromRequest extends CMSServlet { + 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 { + Integer.parseInt(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/pki/base/common/src/com/netscape/cms/servlet/cert/GetEnableStatus.java b/pki/base/common/src/com/netscape/cms/servlet/cert/GetEnableStatus.java new file mode 100644 index 000000000..cac7c3a34 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/GetEnableStatus.java @@ -0,0 +1,174 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ra.*; +import com.netscape.cms.authentication.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; + + +/** + * XXX Servlet to get the enrollment status, enable or disable. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetEnableStatus extends CMSServlet { + 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(); + + // 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 val = configStore.getString("hashDirEnrollment.name"); + IAuthSubsystem authSS = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + IAuthManager authMgr = authSS.get(val); + HashAuthentication mgr = (HashAuthentication) authMgr; + long timeout = mgr.DEFAULT_TIMEOUT / 1000; + + header.addStringValue("timeout", "" + timeout); + header.addStringValue("reqHost", reqHost); + + for (Enumeration hosts = mgr.getHosts(); hosts.hasMoreElements();) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("hosts", (String) 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/pki/base/common/src/com/netscape/cms/servlet/cert/GetInfo.java b/pki/base/common/src/com/netscape/cms/servlet/cert/GetInfo.java new file mode 100644 index 000000000..d1760a21e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/GetInfo.java @@ -0,0 +1,358 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import netscape.security.util.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.dbs.crldb.*; + + +/** + * Get detailed information about CA CRL processing + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetInfo extends CMSServlet { + + 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 = ""; + 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 ipNames = crlRepository.getIssuingPointsNames(); + for (int i = 0; i < ipNames.size(); i++) { + String ipName = (String)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 += "-, -, -"; + } + } + + } else { + Enumeration ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = (ICRLIssuingPoint) 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() == ip.CRL_PUBLISHING_STARTED) { + recentChanges += "Publishing CRL #" + ip.getCRLNumber(); + } else if (ip.isCRLUpdateInProgress() == ip.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 splits = ip.getSplitTimes(); + + for (int i = 0; i < splits.size(); i++) { + crlSplits.append(splits.elementAt(i)); + if (i + 1 < splits.size()) + crlSplits.append(","); + } + } + } + + } + + 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.addBooleanValue("isDeltaCRLEnabled", isDeltaCRLEnabled); + + header.addStringValue("master_host", masterHost); + header.addStringValue("master_port", masterPort); + + header.addStringValue("masterCRLIssuingPoint", mCA.PROP_MASTER_CRL); + ICRLIssuingPoint ip0 = mCA.getCRLIssuingPoint(mCA.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/pki/base/common/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java b/pki/base/common/src/com/netscape/cms/servlet/cert/HashEnrollServlet.java new file mode 100644 index 000000000..f484e2e3d --- /dev/null +++ b/pki/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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.*; +import java.io.*; + +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; + + +import netscape.security.x509.*; +import netscape.security.util.ObjectIdentifier; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.asn1.InvalidBERException; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; + +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.authentication.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; + +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import java.math.*; + + +/** + * XXX performs face-to-face enrollment. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class HashEnrollServlet extends CMSServlet { + 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(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + 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 { + IArgBlock httpParams = cmsReq.getHttpParams(); + 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); + X509CertInfo new_certInfo = 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); + + X509CertInfo authCertInfo = null; + 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); + // } + } + + 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")); + return; + } + } + + // fill certInfo from input types: keygen, cmc, pkcs10 or crmf + KeyGenInfo keyGenInfo = + httpParams.getValueAsKeyGenInfo(SUBJECT_KEYGEN_INFO, null); + + String certType = null; + + // + String test = httpParams.getValueAsString("certNickname", null); + + // 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 { + // 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 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 = (ICertRecord) 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 messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration 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/pki/base/common/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.java new file mode 100644 index 000000000..2e6c693d4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/ImportCertsTemplateFiller.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.cert; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.Locale; +import java.math.BigInteger; +import java.io.ByteArrayOutputStream; +import java.io.StringWriter; +import java.io.StringReader; +import java.io.BufferedReader; + + +import javax.servlet.http.HttpServletRequest; + +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.NoSuchAlgorithmException; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.CertificateChain; +import netscape.security.x509.AlgorithmId; +import netscape.security.pkcs.PKCS7; +import netscape.security.pkcs.ContentInfo; +import netscape.security.pkcs.SignerInfo; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.request.IRequest; + +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.cmmf.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 = com.netscape.osutil.OSUtil.BtoA(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/pki/base/common/src/com/netscape/cms/servlet/cert/ListCerts.java b/pki/base/common/src/com/netscape/cms/servlet/cert/ListCerts.java new file mode 100644 index 000000000..e5d1f9e0f --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/ListCerts.java @@ -0,0 +1,722 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import netscape.security.provider.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Retrieve a paged list of certs matching the specified query + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ListCerts extends CMSServlet { + + private final static String TPL_FILE = "queryCert.template"; + private final static String INFO = "ListCerts"; + private final static BigInteger MINUS_ONE = new BigInteger("-1"); + + private final static String CURRENT_TIME = "currentTime"; + 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 mAllowedClientFilters = new Vector(); + + /** + * 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; + + /* 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 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")); + } + + 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 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 en = tolist.getCertRecords(0, 0); + + if (en == null || (!en.hasMoreElements())) { + toCurIndex = list.getSize() - 1; + } else { + toCurIndex = tolist.getCurrentIndex(); + ICertRecord rx = (ICertRecord) 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()); + + } + + /** + * Process the key search. + */ + private void process(CMSTemplateParams argSet, IArgBlock header, + int maxCount, int sentinel, + String filter, HttpServletRequest req, + HttpServletResponse resp, + String revokeAll, Locale locale) + throws EBaseException { + try { + if (filter.indexOf(CURRENT_TIME, 0) > -1) { + filter = insertCurrentTime(filter); + } + if (revokeAll != null && revokeAll.indexOf(CURRENT_TIME, 0) > -1) { + revokeAll = insertCurrentTime(revokeAll); + } + + // xxx the filter includes serial number range??? + ICertRecordList list = + (ICertRecordList) mCertDB.findCertRecordsInList(filter, null, maxCount); + // sentinel is the index on the list now, not serial number + Enumeration e = + list.getCertRecords(sentinel, sentinel + maxCount - 1); + + int count = 0; + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) e.nextElement(); + + count++; + IArgBlock rarg = com.netscape.certsrv.apps.CMS.createArgBlock(); + + fillRecordIntoArg(rec, rarg); + argSet.addRepeatRecord(rarg); + } + + header.addStringValue("op", req.getParameter("op")); + if (revokeAll != null) + header.addStringValue("revokeAll", revokeAll); + if (mAuthName != null) + header.addStringValue("issuerName", mAuthName.toString()); + header.addStringValue("serviceURL", req.getRequestURI()); + header.addStringValue("templateName", "queryCert"); + header.addStringValue("queryFilter", filter); + header.addIntegerValue("maxCount", maxCount); + header.addIntegerValue("totalRecordCount", list.getSize()); + if ((sentinel + count) < list.getSize()) + header.addIntegerValue("querySentinelDown", sentinel + count); + else + header.addStringValue("querySentinelDown", null); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, com.netscape.certsrv.apps.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(); + if (newFilter.length() == 0) { + newFilter.append(filter.substring(k, i)); + newFilter.append(now.getTime()); + } else { + 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()); + + 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 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/pki/base/common/src/com/netscape/cms/servlet/cert/Monitor.java b/pki/base/common/src/com/netscape/cms/servlet/cert/Monitor.java new file mode 100644 index 000000000..0e3433fe1 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/Monitor.java @@ -0,0 +1,386 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * XXX Provide statistical queries of request and certificate records. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class Monitor extends CMSServlet { + + 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; + } + + /** + * 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 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)) - 1900; + 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)); + + d = new Date(year, month, date, hour, minute, second); + } 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) { + String time = "" + (d.getYear() + 1900); + int i = d.getMonth() + 1; + + if (i < 10) time += "0"; + time += i; + i = d.getDate(); + if (i < 10) time += "0"; + time += i; + i = d.getHours(); + if (i < 10) time += "0"; + time += i; + i = d.getMinutes(); + if (i < 10) time += "0"; + time += i; + i = d.getSeconds(); + 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/pki/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java b/pki/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java new file mode 100644 index 000000000..8f5c2a170 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/ReasonToRevoke.java @@ -0,0 +1,264 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; + + +/** + * Specify the RevocationReason when revoking a certificate + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ReasonToRevoke extends CMSServlet { + + 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 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(); + } + 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); + + 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 e = mCertDB.searchCertificates(revokeAll, + totalRecordCount, mTimeLimits); + + int count = 0; + String errorMsg = null; + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) 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/pki/base/common/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java b/pki/base/common/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java new file mode 100644 index 000000000..14bf38268 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/RemoteAuthConfig.java @@ -0,0 +1,607 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import netscape.ldap.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.logging.*; + +import com.netscape.cms.servlet.*; + + +/** + * Allow agent to turn on/off authentication managers + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class RemoteAuthConfig extends CMSServlet { + + 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 mRemotelySetInstances = new Vector(); + 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(); + + IAuthToken authToken = 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) { + Enumeration eVals = attr.getStringValues(); + + while (eVals.hasMoreElements()) { + String nextValue = (String) eVals.nextElement(); + + if (nextValue.indexOf("Administrator") > -1) { + LDAPEntry groupEntry = c.read(nextValue); + + if (groupEntry != null) { + LDAPAttribute gAttr = groupEntry.getAttribute(UNIQUE_MEMBER); + + if (gAttr != null) { + Enumeration eValues = gAttr.getStringValues(); + + while (eValues.hasMoreElements()) { + String value = (String) 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; + Enumeration eVals = attr.getStringValues(); + + while (eVals.hasMoreElements()) { + String nextValue = (String) eVals.nextElement(); + + if (nextValue.indexOf("Administrator") > -1) { + LDAPEntry groupEntry = c.read(nextValue); + + if (groupEntry != null) { + LDAPAttribute gAttr = groupEntry.getAttribute(UNIQUE_MEMBER); + + if (gAttr != null) { + Enumeration eValues = gAttr.getStringValues(); + + while (eValues.hasMoreElements()) { + String value = (String) 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((String) 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((String) 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 e = mAuthSubsystem.getAuthManagerPlugins(); + + while (e.hasMoreElements()) { + AuthMgrPlugin plugin = (AuthMgrPlugin) 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 e = mAuthSubsystem.getAuthManagers(); + + while (e.hasMoreElements()) { + IAuthManager authManager = (IAuthManager) e.nextElement(); + + if (instanceName.equals(authManager.getName())) { + isListed = true; + break; + } + } + } + + return isListed; + } + + private String makeInstanceName() { + Date now = new Date(); + int y = 1900 + now.getYear(); + String name = "R" + y; + + if (now.getMonth() < 10) name += "0"; + name += now.getMonth(); + if (now.getDate() < 10) name += "0"; + name += now.getDate(); + if (now.getHours() < 10) name += "0"; + name += now.getHours(); + if (now.getMinutes() < 10) name += "0"; + name += now.getMinutes(); + if (now.getSeconds() < 10) name += "0"; + name += now.getSeconds(); + return name; + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/RenewalServlet.java b/pki/base/common/src/com/netscape/cms/servlet/cert/RenewalServlet.java new file mode 100644 index 000000000..00ff0f1b9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/RenewalServlet.java @@ -0,0 +1,517 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; + +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.io.IOException; +import java.math.BigInteger; + +import java.security.cert.X509Certificate; +import java.security.cert.CertificateException; + +import netscape.security.x509.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; + +import com.netscape.certsrv.dbs.certdb.ICertRecord; + +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + +import com.netscape.certsrv.ca.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; +import netscape.security.extensions.*; + +/** + * Certificate Renewal + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class RenewalServlet extends CMSServlet { + // 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) { + notBefore = new Date(beginYear, beginMonth, beginDate); + notAfter = new Date(endYear, endMonth, endDate); + } + } // 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 messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration 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(); + HttpServletRequest httpReq = cmsReq.getHttpReq(); + String certType = httpParams.getValueAsString(CERT_TYPE, "client"); + String agent = httpReq.getHeader("user-agent"); + + 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/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java b/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java new file mode 100644 index 000000000..50f55a4dc --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationServlet.java @@ -0,0 +1,366 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.Enumeration; +import java.util.Locale; +import java.io.IOException; +import java.math.BigInteger; + +import java.security.cert.X509Certificate; +import java.security.cert.CertificateEncodingException; + +import netscape.security.x509.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; + +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authentication.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.apps.*; + + +/** + * Perform the first step in revoking a certificate + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class RevocationServlet extends CMSServlet { + 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; + + 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; + + // 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; + String revokeAll = 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); + + 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 enum1 = req.getExtDataKeys(); + + while (enum1.hasMoreElements()) { + String name = (String) 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", com.netscape.osutil.OSUtil.BtoA(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/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.java new file mode 100644 index 000000000..efcb53f60 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/RevocationSuccessTemplateFiller.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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.cert; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; + +import netscape.security.x509.RevokedCertImpl; + +import org.mozilla.jss.ssl.SSLSocket; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.cms.servlet.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/cert/SrchCerts.java b/pki/base/common/src/com/netscape/cms/servlet/cert/SrchCerts.java new file mode 100644 index 000000000..4008bc4e8 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/SrchCerts.java @@ -0,0 +1,764 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import netscape.security.provider.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * XXX Search for certificates matching complex query filter + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class SrchCerts extends CMSServlet { + + 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 ICertificateRepository mCertDB = null; + private X500Name mAuthName = null; + private String mFormPath = null; + private int mMaxReturns = 100; + 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, 100); + } 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 { + 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 StringBuffer escapeValueRfc1779(String v) + { + 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 == '"') { + result.append('\\'); + } + result.append(c); + } + return result; + } + + 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)); + lf.append(",*)"); + lf.append("(x509cert.subject=*"); + lf.append(avaName); + lf.append("="); + lf.append(escapeValueRfc1779(val)); + lf.append(")"); + lf.append(")"); + } else { + lf.append("(x509cert.subject=*"); + lf.append(avaName); + lf.append("="); + lf.append("*"); + lf.append(escapeValueRfc1779(val)); + 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) + { + String queryCertFilter = null; + 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??? + int mr = (maxResults > 0) ? maxResults : mMaxReturns; + if (timeLimit == -1 || timeLimit > mTimeLimits) { + CMS.debug("Resetting timelimit from " + timeLimit + " to " + mTimeLimits); + timeLimit = mTimeLimits; + } + CMS.debug("Start searching ... " + "filter=" + filter + " maxreturns=" + mr + " timelimit=" + timeLimit); + Enumeration e = mCertDB.searchCertificates(filter, mr, timeLimit); + + int count = 0; + + while (e != null && e.hasMoreElements()) { + ICertRecord rec = (ICertRecord) 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", mr); + } 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 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/pki/base/common/src/com/netscape/cms/servlet/cert/UpdateCRL.java b/pki/base/common/src/com/netscape/cms/servlet/cert/UpdateCRL.java new file mode 100644 index 000000000..1c553b3a7 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/UpdateCRL.java @@ -0,0 +1,337 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import netscape.security.util.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Force the CRL to be updated now. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class UpdateCRL extends CMSServlet { + + private final static String INFO = "UpdateCRL"; + private final static String TPL_FILE = "updateCRL.template"; + + 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 */); + } + + long startTime = CMS.getCurrentDate().getTime(); + 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 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"); + + if (crlIssuingPointId != null) { + Enumeration ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = (ICRLIssuingPoint) ips.nextElement(); + + if (crlIssuingPointId.equals(ip.getId())) { + break; + } + if (!ips.hasMoreElements()) crlIssuingPointId = null; + } + } + if (crlIssuingPointId == null) { + crlIssuingPointId = mCA.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) { + 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()) { + 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/pki/base/common/src/com/netscape/cms/servlet/cert/UpdateDir.java b/pki/base/common/src/com/netscape/cms/servlet/cert/UpdateDir.java new file mode 100644 index 000000000..e918beb7b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/UpdateDir.java @@ -0,0 +1,734 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.ca.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Update the configured LDAP server with specified objects + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class UpdateDir extends CMSServlet { + + 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 ips = mCA.getCRLIssuingPoints(); + + while (ips.hasMoreElements()) { + ICRLIssuingPoint ip = (ICRLIssuingPoint) 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 ipNames = mCRLRepository.getIssuingPointsNames(); + if (ipNames != null && ipNames.size() > 0) { + for (int i = 0; i < ipNames.size(); i++) { + String ipName = (String)ipNames.elementAt(i); + + updateCRLIssuingPoint(header, ipName, null, locale); + } + } + } else { + Enumeration oips = mCA.getCRLIssuingPoints(); + + while (oips.hasMoreElements()) { + ICRLIssuingPoint oip = (ICRLIssuingPoint) oips.nextElement(); + + updateCRLIssuingPoint(header, oip.getId(), oip, locale); + } + } + } else { + ICRLIssuingPoint crlIssuingPoint = + mCA.getCRLIssuingPoint(crlIssuingPointId); + ICRLIssuingPointRecord crlRecord = null; + + 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 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 = + (ICertRecord) 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 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 = + (ICertRecord) 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 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 = + (ICertRecord) 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/pki/base/common/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java b/pki/base/common/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java new file mode 100644 index 000000000..b6b75e6e0 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/scep/CRSEnrollment.java @@ -0,0 +1,1876 @@ +// --- 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.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import java.security.*; +import java.security.MessageDigest; + +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import netscape.security.util.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authentication.AuthCredentials; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cms.servlet.profile.*; +import org.mozilla.jss.pkcs7.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkix.cert.Certificate; +import com.netscape.cmsutil.scep.CRSPKIMessage; + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CRSEnrollment extends HttpServlet +{ + 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; + 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 toHashtable(HttpServletRequest req) { + Hashtable httpReqHash = new Hashtable(); + 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) { + // 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 { + mProfileSubsystem = (IProfileSubsystem)CMS.getSubsystem("profile"); + mProfileId = sc.getInitParameter("profileId"); + + 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) { + } + + } + + + /** + * + * 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; + + + // 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 (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 (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); + } + + public IAuthToken authenticate(AuthCredentials credentials, IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + + // build credential + Enumeration authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = (String) authNames.nextElement(); + + credentials.set(authName, request.getParameter(authName)); + } + } + + credentials.set("clientHost", request.getRemoteHost()); + IAuthToken authToken = authenticator.authenticate(credentials); + 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); + + bytes = chain[i].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 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 = com.netscape.osutil.OSUtil.AtoB(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); + } + 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); + + // 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 Nonces + byte[] sn = req.getSenderNonce(); + + // 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 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 exts = ((ExtensionsRequested)attr).getExtensions().elements(); + while (exts.hasMoreElements()) { + Extension ext = (Extension) exts.nextElement(); + + if (ext.getExtensionId().equals( + OIDMap.getOID(SubjectAlternativeNameExtension.IDENT)) ) { + DerOutputStream dos = new DerOutputStream(); + SubjectAlternativeNameExtension sane = new SubjectAlternativeNameExtension( + Boolean.valueOf(false), // noncritical + ext.getExtensionValue()); + + + Vector v = + (Vector) sane.get(SubjectAlternativeNameExtension. SUBJECT_NAME); + + Enumeration gne = v.elements(); + + StringBuffer subjAltNameStr = new StringBuffer(); + 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(); + + 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 (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(); + + 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 = com.netscape.osutil.OSUtil.AtoB(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); + crsResp = new CRSPKIMessage(); + } + catch (Exception e) { + CMS.debug(e); + throw new ServletException("Could not decode the request."); + } + crsResp.setMessageType(crsResp.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 { + crsResp.setRecipientNonce(sn); + 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(req.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(req.mType_GetCertInitial)) { + CMS.debug("Processing GetCertInitial"); + cert = handleGetCertInitial(req,crsResp); + } else { + CMS.debug("Invalid request type " + mt); + } + } + catch (CRSInvalidSignatureException e) { + CMS.debug("handlePKIMessage exception " + e); + CMS.debug(e); + crsResp.setFailInfo(crsResp.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(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 rids = rq.findRequestsBySourceId(txid); + if (rids == null) { return null; } + + int count=0; + while (rids.hasMoreElements()) { + RequestId rid = (RequestId) 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; + + resp.setRecipientNonce(req.getSenderNonce()); + resp.setSenderNonce(null); + + try { + foundRequest = findRequestByTransactionID(req.getTransactionID(),false); + } catch (EBaseException e) { + } + + if (foundRequest == null) { + resp.setFailInfo(resp.mFailInfo_badCertId); + resp.setPKIStatus(resp.mStatus_FAILURE); + return null; + } + + return makeResponseFromRequest(req,resp,foundRequest); + } + + + public void verifyRequest(CRSPKIMessage req, CryptoContext cx) + throws CRSInvalidSignatureException { + + // Get Signed Data + + byte[] reqAAbytes = req.getAA(); + byte[] reqAAsig = req.getAADigest(); + + } + + + /** + * 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; + KeyWrapper kw; + Cipher cip; + boolean errorInRequest = false; + + // Unwrap the session key with the Cert server key + try { + kw = cx.getKeyWrapper(); + + kw.initUnwrap(cx.getPrivateKey(),null); + + sk = kw.unwrapSymmetric(req.getWrappedKey(), + SymmetricKey.Type.DES, + SymmetricKey.Usage.DECRYPT, + 0); // keylength is ignored + + skinternal = cx.getDESKeyGenerator().clone(sk); + + cip = skinternal.getOwningToken().getCipherContext(EncryptionAlgorithm.DES_CBC); + + 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 { + + IRequest issueReq = null; + X509CertImpl issuedCert=null; + Vector extensionsRequested = null; + SubjectAlternativeNameExtension sane = null; + CertAttrSet requested_ext = null; + + try { + PKCS10 p10 = (PKCS10)req.getP10(); + + if (p10 == null) { + crsResp.setFailInfo(crsResp.mFailInfo_badMessageCheck); + crsResp.setPKIStatus(crsResp.mStatus_FAILURE); + throw new CRSFailureException("Failed to decode pkcs10 from CEP request"); + } + + AuthCredentials authCreds = new AuthCredentials(); + + String challengePassword = null; + // 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 rdne = p10subject.getRDNs(); + Vector rdnv = new Vector(); + + Hashtable sanehash = new Hashtable(); + + 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 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 exts = ((ExtensionsRequested)attr).getExtensions().elements(); + while (exts.hasMoreElements()) { + Extension ext = (Extension) 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)) ) { + DerOutputStream dos = new DerOutputStream(); + sane = new SubjectAlternativeNameExtension( + new Boolean(false), // noncritical + ext.getExtensionValue()); + + + Vector v = + (Vector) sane.get(SubjectAlternativeNameExtension. SUBJECT_NAME); + + Enumeration 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("")) { + + X500Name newSubject = new X500Name(subject.toString()); + 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(crsResp.mFailInfo_badMessageCheck); + crsResp.setPKIStatus(crsResp.mStatus_FAILURE); + return ; + } // NEED TO FIX + } + + + private SubjectAlternativeNameExtension makeDefaultSubjectAltName(Hashtable 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 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 fingerprints) + { + + Hashtable old_fprints = req.getExtDataInHashtable(IRequest.FINGERPRINTS); + if (old_fprints == null) { return false; } + + byte[] old_md5 = CMS.AtoB((String) old_fprints.get("MD5")); + byte[] new_md5 = (byte[]) 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 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(crsResp.mFailInfo_badRequest); + crsResp.setPKIStatus(crsResp.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(crsResp.mFailInfo_badIdentity); + crsResp.setPKIStatus(crsResp.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(crsResp.mFailInfo_badMessageCheck); + crsResp.setPKIStatus(crsResp.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(crsResp.mFailInfo_internalCAError); + crsResp.setPKIStatus(crsResp.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 = (PKCS10)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].setExtData("profileId", mProfileId); + reqs[0].setSourceId(req.getTransactionID()); + + 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"); + + 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 encodedPrints = new Hashtable(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(crsResp.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 makeFingerPrints(CRSPKIMessage req) { + Hashtable fingerprints = new Hashtable(); + + MessageDigest md; + String[] hashes = new String[] {"MD2", "MD5", "SHA1"}; + 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(crsResp.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(crsResp.mStatus_SUCCESS); + + } + else { // status is not 'success' - there must've been a problem + + crsResp.setPKIStatus(crsResp.mStatus_FAILURE); + crsResp.setFailInfo(crsResp.mFailInfo_badAlg); + } + } + else if (status.equals(RequestStatus.REJECTED_STRING) || + status.equals(RequestStatus.CANCELED_STRING)) { + crsResp.setPKIStatus(crsResp.mStatus_FAILURE); + crsResp.setFailInfo(crsResp.mFailInfo_badRequest); + } + else { // not complete + crsResp.setPKIStatus(crsResp.mStatus_PENDING); + } + + return issuedCert; + } + + + + + + + /** + * This needs to be re-written to log the messages to the system log, since there + * will be no visual webpage feedback for the user. (he's using a router) + */ + + private void writeError(String errMsg, HttpServletRequest httpReq, + HttpServletResponse httpResp) + throws IOException + { + } + + + protected String hashPassword(String pwd) { + String salt = "lala123"; + byte[] pwdDigest = mSHADigest.digest((salt+pwd).getBytes()); + String b64E = com.netscape.osutil.OSUtil.BtoA(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; + + // 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(KeyGenAlgorithm.DES).clone(sk); + + byte[] padded = Cipher.pad(toBeEncrypted, + EncryptionAlgorithm.DES_CBC.getBlockSize()); + + + // This should be changed to generate proper DES IV. + + Cipher cipher = cx.getInternalToken().getCipherContext(EncryptionAlgorithm.DES_CBC); + 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); + + // 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("MD5"); + 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()); + + // 11. Make SignedData + crsResp.makeSignedData(1, signingcertbytes); + + 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 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 { + public CryptoContextException() { super(); } + public CryptoContextException(String s) { super(s); } + } + + public CryptoContext() + throws CryptoContextException + { + try { + cm = CryptoManager.getInstance(); + internalToken = cm.getInternalCryptoToken(); + internalKeyStorageToken = cm.getInternalKeyStorageToken(); + DESkg = internalToken.getKeyGenerator(KeyGenAlgorithm.DES); + signingCert = cm.findCertByNickname(ca.getNickname()); + 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()); + } + } + + + 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 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 { + public CRSFailureException() { super(); } + public CRSFailureException(String s) { super(s); } + } + + class CRSInvalidSignatureException extends Exception { + public CRSInvalidSignatureException() { super(); } + public CRSInvalidSignatureException(String s) { super(s); } + } + + + + class CRSPolicyException extends Exception { + public CRSPolicyException() { super(); } + public CRSPolicyException(String s) { super(s); } + } + +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java b/pki/base/common/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.java new file mode 100644 index 000000000..3e94228a1 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/scep/ChallengePassword.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.scep; + +import java.io.*; +import java.security.*; +import java.util.Properties; +import java.util.*; + +import netscape.security.util.*; +import netscape.security.x509.*; +import com.netscape.cmsutil.scep.*; +import java.security.cert.CertificateException; + +/** + * 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 getElements() + { return (new Hashtable()).elements();} + + /** + * @return the String "ChallengePassword" + */ + public String getName() + { return NAME;} + + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java b/pki/base/common/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.java new file mode 100644 index 000000000..616eab27b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/cert/scep/ExtensionsRequested.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.cert.scep; + +import java.io.*; +import java.security.*; +import java.util.Properties; +import java.util.*; + +import netscape.security.util.*; +import netscape.security.x509.*; +import java.security.cert.CertificateException; +import com.netscape.cmsutil.scep.*; + + +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 exts = new Vector(); + + 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 getElements() + { return (new Hashtable()).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; + DerValue[] dvs; + + try { // try decoding as sequence first + + stream = dv.toDerInputStream(); + + DerValue stream_dv = stream.getDerValue(); + stream.reset(); + + + dvs = stream.getSequence(2); + } + 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(); + dvs = stream.getSequence(2); + } + + // 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 getExtensions() { + return exts; + } + +} + + diff --git a/pki/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java b/pki/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java new file mode 100644 index 000000000..a2483b8a4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/AuthCredentials.java @@ -0,0 +1,100 @@ +// --- 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.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; + + +/** + * Authentication Credentials as input to the authMgr + * <P> + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class AuthCredentials implements IAuthCredentials { + private Hashtable authCreds = null; + // Inserted by bskim + private IArgBlock argblk = null; + // Insert end + + public AuthCredentials() { + authCreds = new Hashtable(); + } + + /** + * 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 ((Object) 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 credentials in this credential + * set. Use the Enumeration methods on the returned object to + * fetch the elements sequentially. + * @return an enumeration of the values in this credential set + * @see java.util.Enumeration + */ + public Enumeration getElements() { + return (authCreds.elements()); + } + + // Inserted by bskim + public void setArgBlock(IArgBlock blk) { + argblk = blk; + return; + } + + // Insert end + + public IArgBlock getArgBlock() { + return argblk; + } + // Insert end +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java new file mode 100644 index 000000000..d83c1bf67 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMCOutputTemplate.java @@ -0,0 +1,1060 @@ +// --- 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 org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkix.cmmf.*; +import org.mozilla.jss.pkix.primitive.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.http.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.dbs.certdb.ICertificateRepository; +import com.netscape.certsrv.base.SessionContext; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cert.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.*; +import netscape.security.x509.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.ca.*; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import org.mozilla.jss.pkcs11.PK11PubKey; + +/** + * Utility CMCOutputTemplate + * + * @version $ $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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); + // SHA1 is the default digest Alg for now. + DigestAlgorithm digestAlg = null; + SignatureAlgorithm signAlg = null; + 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 { + CMS.debug( "CMCOutputTemplate::getContentInfo() - " + + "signAlg is unsupported!" ); + return null; + } + + MessageDigest SHADigest = null; + byte[] digest = null; + + SHADigest = MessageDigest.getInstance("SHA1"); + digestAlg = DigestAlgorithm.SHA1; + + ByteArrayOutputStream ostream = new ByteArrayOutputStream(); + + respBody.encode((OutputStream) ostream); + digest = SHADigest.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); + 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(); + X509CertImpl impl = null; + try { + repository.getX509Certificate(serialno); + } catch (EBaseException ee) { + CMS.debug("CMCOutputTemplate: Certificate in the confirm acceptance control was not found"); + } + if (impl != null) + confirmAccepted = true; + } + 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) { + Integer result = r.getExtDataInInteger(IRequest.RESULT); + 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; + } + + byte[] bv = null; + 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 digs = new Hashtable(); + 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 = (byte[]) 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/pki/base/common/src/com/netscape/cms/servlet/common/CMSFile.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSFile.java new file mode 100644 index 000000000..354744261 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSFile.java @@ -0,0 +1,104 @@ +// --- 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.*; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.base.EBaseException; + + +/** + * CMSFile represents a file from the filesystem cached in memory + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/CMSFileLoader.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSFileLoader.java new file mode 100644 index 000000000..915c73e53 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSFileLoader.java @@ -0,0 +1,163 @@ +// --- 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.Hashtable; +import java.util.Enumeration; + +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.EBaseException; + + +/** + * CMSFileLoader - file cache. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ + +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 mLoadedFiles = new Hashtable(); + + // 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 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 = (CMSFile) elements.nextElement(); + + if (cmsFile.getLastAccess() < lru) { + lruFile = cmsFile; + } + mLoadedFiles.remove(lruFile.getAbsPath()); + } + } + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/common/CMSGWResources.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSGWResources.java new file mode 100644 index 000000000..4c840d6d9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSGWResources.java @@ -0,0 +1,46 @@ +// --- 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.*; + + +/** + * A class represents a resource bundle for cms gateway. + * <P> + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + * @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/pki/base/common/src/com/netscape/cms/servlet/common/CMSGateway.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSGateway.java new file mode 100644 index 000000000..c28fdbcb1 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSGateway.java @@ -0,0 +1,369 @@ +// --- 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.*; +import java.util.*; + +import java.util.Locale; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletConfig; +import javax.servlet.ServletOutputStream; + +import java.security.cert.X509Certificate; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; + +import com.netscape.certsrv.logging.ILogger; + + +/** + * This class is to hold some general method for servlets. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 toHashtable(HttpServletRequest req) { + Hashtable httpReqHash = new Hashtable(); + Enumeration names = req.getParameterNames(); + + while (names.hasMoreElements()) { + String name = (String) 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/pki/base/common/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java new file mode 100644 index 000000000..bd2f76c75 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSLoadTemplate.java @@ -0,0 +1,64 @@ +// --- 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.logging.*; + + +/** + * handy class containing cms templates to load & fill. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/CMSRequest.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSRequest.java new file mode 100644 index 000000000..b458e0b81 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSRequest.java @@ -0,0 +1,298 @@ +// --- 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.Vector; +import java.util.Hashtable; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletContext; +import javax.servlet.ServletConfig; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.request.RequestId; +import com.netscape.certsrv.apps.*; + +/** + * This represents a user request. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 mErrorDescr = null; + + // any request resulting data; + Object mResult = null; + Hashtable mResults = new Hashtable(); + + /** + * 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(); + 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 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 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/pki/base/common/src/com/netscape/cms/servlet/common/CMSTemplate.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSTemplate.java new file mode 100644 index 000000000..8d6166dbd --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSTemplate.java @@ -0,0 +1,549 @@ +// --- 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.lang.*; +import java.io.*; +import java.util.*; +import java.math.BigInteger; +import javax.servlet.*; +import javax.servlet.http.*; +import java.io.StringWriter; +import java.io.PrintWriter; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 { + StringBuffer buf = new StringBuffer(); + + /* 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 e = null, q = null; + IArgBlock r = null; + boolean headerBlock = false, fixedBlock = false, queryBlock = false; + 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()) { + headerBlock = true; + String n = (String) 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()) { + fixedBlock = true; + String n = (String) 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()) { + queryBlock = true; + 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 = (IArgBlock) q.nextElement(); + e = r.elements(); + while (e.hasMoreElements()) { + String n = (String) 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 * 2]; + int j = 0; + + v.getChars(0, l, in, 0); + + for (int i = 0; i < l; i++) { + char c = in[i]; + + if (c > 0x23) { + out[j++] = c; + 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; + + 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 > 0x5B) { + out[j++] = c; + 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 '<': + out[j++] = '&'; + out[j++] = 'l'; + out[j++] = 't'; + out[j++] = ';'; + 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; + } + + public void println(String s) throws IOException { + print(s); + write('\n'); + flush(); + return; + } + } + + + private class templateLine { + private StringBuffer s = new StringBuffer(); + void templateLine() { + } + + 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/pki/base/common/src/com/netscape/cms/servlet/common/CMSTemplateParams.java b/pki/base/common/src/com/netscape/cms/servlet/common/CMSTemplateParams.java new file mode 100644 index 000000000..05008c88f --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/CMSTemplateParams.java @@ -0,0 +1,73 @@ +// --- 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 java.util.Locale; + +import com.netscape.certsrv.base.*; + + +/** + * Holds template parameters + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CMSTemplateParams { + private IArgBlock mHeader = null; + private IArgBlock mFixed = null; + private Vector mRepeat = new Vector(); + + 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(); + } + + public Enumeration queryRecords() { + return mRepeat.elements(); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/common/ECMSGWException.java b/pki/base/common/src/com/netscape/cms/servlet/common/ECMSGWException.java new file mode 100644 index 000000000..086274fac --- /dev/null +++ b/pki/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 java.util.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; + + +/** + * A class represents a CMS gateway exception. + * <P> + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ECMSGWException extends EBaseException { + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/GenErrorTemplateFiller.java new file mode 100644 index 000000000..b50c9e0d7 --- /dev/null +++ b/pki/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.Locale; +import java.util.Vector; +import java.util.Enumeration; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; + + +/** + * Default error template filler + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 descr = cmsReq.getErrorDescr(); + + if (descr != null) { + Enumeration num = descr.elements(); + + while (num.hasMoreElements()) { + String elem = (String) 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/pki/base/common/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java new file mode 100644 index 000000000..db4030d85 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/GenPendingTemplateFiller.java @@ -0,0 +1,270 @@ +// --- 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 java.util.Date; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.RequestId; +import netscape.security.x509.*; +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.CryptoToken; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cert.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.asn1.*; +import java.io.*; +import java.security.*; + + +/** + * default Pending template filler + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java new file mode 100644 index 000000000..5f0487976 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/GenRejectedTemplateFiller.java @@ -0,0 +1,95 @@ +// --- 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 java.util.Vector; +import java.util.Enumeration; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.request.IRequest; + + +/** + * default Service Pending template filler + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 messages = req.getExtDataInStringVector(IRequest.ERRORS); + + if (messages != null) { + Enumeration msgs = messages.elements(); + + while (msgs.hasMoreElements()) { + String ex = (String) 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/pki/base/common/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java new file mode 100644 index 000000000..ea292537f --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/GenSuccessTemplateFiller.java @@ -0,0 +1,65 @@ +// --- 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.*; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.apps.CMS; + + +/** + * default Success template filler + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.java new file mode 100644 index 000000000..eaa63bdbc --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/GenSvcPendingTemplateFiller.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) 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.*; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.apps.CMS; + + +/** + * default Service Pending template filler + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.java new file mode 100644 index 000000000..b499cb24c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/GenUnauthorizedTemplateFiller.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) 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.*; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.apps.*; + + +/** + * default Unauthorized template filler + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java new file mode 100644 index 000000000..404a71971 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/GenUnexpectedErrorTemplateFiller.java @@ -0,0 +1,78 @@ +// --- 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.*; +import com.netscape.certsrv.base.IArgBlock; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.BaseResources; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.apps.*; + + +/** + * default unexpected error template filler + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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); + + // request status if any. + if (cmsReq != null) { + Integer sts = cmsReq.getStatus(); + + if (sts != null) + 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/pki/base/common/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.java new file mode 100644 index 000000000..a5a7e6663 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/ICMSTemplateFiller.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.common; + + +import java.util.Locale; +import com.netscape.certsrv.authority.*; + + +/** + * This interface represents a template filler. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/IRawJS.java b/pki/base/common/src/com/netscape/cms/servlet/common/IRawJS.java new file mode 100644 index 000000000..91998f5a9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/IRawJS.java @@ -0,0 +1,27 @@ +// --- 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public interface IRawJS { +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java b/pki/base/common/src/com/netscape/cms/servlet/common/IndexTemplateFiller.java new file mode 100644 index 000000000..8d7da5754 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/IndexTemplateFiller.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.common; + + +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/common/RawJS.java b/pki/base/common/src/com/netscape/cms/servlet/common/RawJS.java new file mode 100644 index 000000000..6f39a2553 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/RawJS.java @@ -0,0 +1,36 @@ +// --- 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class RawJS implements IRawJS { + private String mRawJSstr = null; + + public RawJS(String s) { + mRawJSstr = s; + } + + public String toString() { + return mRawJSstr; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/common/Utils.java b/pki/base/common/src/com/netscape/cms/servlet/common/Utils.java new file mode 100644 index 000000000..1506ababc --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/common/Utils.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.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Utility class + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class Utils { + + 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/pki/base/common/src/com/netscape/cms/servlet/connector/CloneServlet.java b/pki/base/common/src/com/netscape/cms/servlet/connector/CloneServlet.java new file mode 100644 index 000000000..3acf26b41 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/connector/CloneServlet.java @@ -0,0 +1,567 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.connector; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; + +import java.security.cert.*; + +import java.io.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.connector.*; + +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authentication.AuthCredentials; + +import com.netscape.certsrv.apps.*; + + +/** + * Clone servlet - part of the Clone Authority (CLA) + * processes Revoked certs from its dependant clone CAs + * service request and return status. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CloneServlet extends CMSServlet { + 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."); + + ServletContext servletContext = mConfig.getServletContext(); + + 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; + IRequest r = null; + IRequest reply = null; + + // NOTE must read all bufer before redoing handshake for + // ssl client auth for client auth to work. + + // get request method + method = req.getMethod(); + + // get content length + len = 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; + IRequest r = 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/pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java b/pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java new file mode 100644 index 000000000..bf16a87c8 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/connector/ConnectorServlet.java @@ -0,0 +1,1092 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.connector; + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +//import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import java.io.*; +import java.util.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.connector.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.profile.*; + +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.apps.*; + + +/** + * Connector servlet + * process requests from remote authority - + * service request or return status. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ConnectorServlet extends CMSServlet { + public static final String INFO = "Connector Servlet"; + public final static String PROP_AUTHORITY = "authority"; + protected ServletConfig mConfig = null; + protected IAuthority mAuthority = null; + protected IRequestEncoder mReqEncoder = null; + protected IAuthSubsystem mAuthSubsystem = null; + protected ILogger mLogger = CMS.getLogger(); + + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + private final static String SIGNED_AUDIT_PROTECTION_METHOD_SSL = "ssl"; + private final static String SIGNED_AUDIT_PROTECTION_METHOD_UNKNOWN = + "unknown"; + private final static String LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS = + "LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS_5"; + private final static String LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST = + "LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST_5"; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + + public ConnectorServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mConfig = sc; + String authority = sc.getInitParameter(PROP_AUTHORITY); + + if (authority != null) + mAuthority = (IAuthority) + CMS.getSubsystem(authority); + mReqEncoder = CMS.getHttpRequestEncoder(); + + mAuthSubsystem = (IAuthSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTH); + } + + public void service(HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + + boolean running_state = CMS.isInRunningState(); + + if (!running_state) + throw new IOException( + "CMS server is not ready to serve."); + + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse resp = (HttpServletResponse) response; + + ServletContext servletContext = mConfig.getServletContext(); + + CMSRequest cmsRequest = newCMSRequest(); + + // set argblock + cmsRequest.setHttpParams(CMS.createArgBlock(toHashtable(request))); + + // set http request + cmsRequest.setHttpReq(request); + + // set http response + cmsRequest.setHttpResp(response); + + // set servlet config. + cmsRequest.setServletConfig(mConfig); + + // set servlet context. + cmsRequest.setServletContext(mConfig.getServletContext()); + + char[] content = null; + String encodedreq = null; + String method = null; + int len = -1; + IPKIMessage msg = null; + IPKIMessage replymsg = null; + IRequest r = null; + IRequest reply = null; + + // NOTE must read all bufer before redoing handshake for + // ssl client auth for client auth to work. + + // get request method + method = req.getMethod(); + + // get content length + len = request.getContentLength(); + + // get content, a base 64 encoded serialized request. + if (len > 0) { + InputStream in = request.getInputStream(); + InputStreamReader inreader = new InputStreamReader(in, "UTF8"); + BufferedReader reader = new BufferedReader(inreader, len); + + content = new char[len]; + int done = reader.read(content, 0, len); + int total = done; + + while (done >= 0 && total < len) { + done = reader.read(content, total, len - total); + total += done; + } + reader.close(); + encodedreq = new String(content); + } + + // force client auth handshake, validate RA and get RA's Id. + // NOTE must do this after all contents are read for ssl + // redohandshake to work + + X509Certificate peerCert; + + try { + peerCert = getPeerCert(req); + }catch (EBaseException e) { + mAuthority.log(ILogger.LL_SECURITY, + CMS.getLogMessage("CMSGW_HAS_NO_CLIENT_CERT")); + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + if (peerCert == null) { + // XXX log something here. + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + // authenticate RA + + String RA_Id = null; + String raUserId = null; + IAuthToken token = null; + + try { + token = authenticate(request); + raUserId = token.getInString("userid"); + RA_Id = (String) peerCert.getSubjectDN().toString(); + } catch (EInvalidCredentials e) { + // already logged. + resp.sendError(HttpServletResponse.SC_UNAUTHORIZED); + return; + } catch (EBaseException e) { + // already logged. + resp.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + + mAuthority.log(ILogger.LL_INFO, + "Remote Authority authenticated: " + peerCert.getSubjectDN()); + + // authorize + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, token, + mAuthzResourceName, "submit"); + } catch (Exception e) { + // do nothing for now + } + + if (authzToken == null) { + cmsRequest.setStatus(CMSRequest.UNAUTHORIZED); + return; + } + + // after cert validated, check http request. + if (!method.equalsIgnoreCase("POST")) { + resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED); + return; + } + if (len <= 0) { + resp.sendError(HttpServletResponse.SC_LENGTH_REQUIRED); + return; + } + + // now process request. + + CMS.debug("ConnectorServlet: process request RA_Id=" + RA_Id); + try { + // decode request. + msg = (IPKIMessage) mReqEncoder.decode(encodedreq); + // process request + replymsg = processRequest(RA_Id, raUserId, msg, token); + } catch (IOException e) { + CMS.debug("ConnectorServlet: service " + e.toString()); + CMS.debug(e); + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + resp.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } catch (EBaseException e) { + CMS.debug("ConnectorServlet: service " + e.toString()); + CMS.debug(e); + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSGW_IO_ERROR_REMOTE_REQUEST", e.toString())); + resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + return; + } catch (Exception e) { + CMS.debug("ConnectorServlet: service " + e.toString()); + CMS.debug(e); + } + + CMS.debug("ConnectorServlet: done processRequest"); + + // encode reply + try { + String encodedrep = mReqEncoder.encode(replymsg); + + resp.setStatus(HttpServletResponse.SC_OK); + resp.setContentType("text/html"); + resp.setContentLength(encodedrep.length()); + + // send reply + OutputStream out = response.getOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(out, "UTF8"); + + writer.write(encodedrep); + writer.flush(); + writer.close(); + out.flush(); + } catch (Exception e) { + CMS.debug("ConnectorServlet: error writing e=" + e.toString()); + } + CMS.debug("ConnectorServlet: send response RA_Id=" + RA_Id); + } + + public static boolean isProfileRequest(IRequest request) { + String profileId = request.getExtDataInString("profileId"); + + if (profileId == null || profileId.equals("")) + return false; + else + return true; + } + + public void normalizeProfileRequest(IRequest request) { + // if it is profile request, we need to normalize the + // x509certinfo from ra into request + X509CertInfo info = null; + ByteArrayOutputStream byteStream; + + try { + info = request.getExtDataInCertInfo(IEnrollProfile.REQUEST_CERTINFO); + + // request.set(IEnrollProfile.REQUEST_SEQ_NUM, new Integer("0")); + CertificateX509Key certKey = (CertificateX509Key)info.get(X509CertInfo.KEY); + if (certKey != null) { + byteStream = new ByteArrayOutputStream(); + certKey.encode(byteStream); + request.setExtData(IEnrollProfile.REQUEST_KEY, + byteStream.toByteArray()); + } + + CertificateSubjectName certSubject = (CertificateSubjectName) + info.get(X509CertInfo.SUBJECT); + if (certSubject != null) { + request.setExtData(IEnrollProfile.REQUEST_SUBJECT_NAME, + certSubject); + } + + CertificateValidity certValidity = (CertificateValidity) + info.get(X509CertInfo.VALIDITY); + if (certValidity != null) { + byteStream = new ByteArrayOutputStream(); + certValidity.encode(byteStream); + request.setExtData(IEnrollProfile.REQUEST_VALIDITY, + byteStream.toByteArray()); + } + + CertificateExtensions extensions = (CertificateExtensions) + info.get(X509CertInfo.EXTENSIONS); + if (extensions != null) { + request.setExtData(IEnrollProfile.REQUEST_EXTENSIONS, + extensions); + } + + CertificateAlgorithmId certAlg = (CertificateAlgorithmId) + info.get(X509CertInfo.ALGORITHM_ID); + if (certAlg != null) { + ByteArrayOutputStream certAlgOut = new ByteArrayOutputStream(); + certAlg.encode(certAlgOut); + request.setExtData(IEnrollProfile.REQUEST_SIGNING_ALGORITHM, + certAlgOut.toByteArray()); + } + } catch (Exception e) { + CMS.debug("ConnectorServlet: profile normalization " + + e.toString()); + } + + String profileId = request.getExtDataInString("profileId"); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem("profile"); + IEnrollProfile profile = null; + + // profile subsystem may not be available. In case of KRA for + // example + if (ps == null) { + CMS.debug("ConnectorServlet: Profile Subsystem not found "); + return; + } + try { + profile = (IEnrollProfile) (ps.getProfile(profileId)); + profile.setDefaultCertInfo(request); + } catch (EProfileException e) { + CMS.debug("ConnectorServlet: normalizeProfileRequest Exception: " + e.toString()); + } + if (profile == null) { + CMS.debug("ConnectorServlet: Profile not found " + profileId); + return; + } + } + + /** + * Process request + * <P> + * + * (Certificate Request - all "agent" profile cert requests made through a + * connector) + * <P> + * + * (Certificate Request Processed - all automated "agent" profile based + * cert acceptance made through a connector) + * <P> + * + * <ul> + * <li>signed.audit LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST used when a + * profile cert request is made (before approval process) + * <li>signed.audit LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED used when a + * certificate request has just been through the approval process + * <li>signed.audit LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS used when + * inter-CIMC_Boundary data transfer is successful (this is used when data + * does not need to be captured) + * </ul> + * @param source string containing source + * @param sourceUserId string containing source user ID + * @param msg PKI message + * @param token the authentication token + * @exception EBaseException an error has occurred + * @return PKI message + */ + protected IPKIMessage processRequest( + String source, String sourceUserId, IPKIMessage msg, IAuthToken token) + throws EBaseException { + String auditMessage = null; + String auditSubjectID = sourceUserId; + String auditProtectionMethod = SIGNED_AUDIT_PROTECTION_METHOD_SSL; + String auditRequestType = msg.getReqType(); + String auditRequesterID = msg.getReqId(); + + // additional parms for LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + String auditCertificateSubjectName = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + String subject = null; + + // additional parms for LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED + String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + // "normalize" the "auditSubjectID" + if (auditSubjectID != null) { + auditSubjectID = auditSubjectID.trim(); + } else { + auditSubjectID = ILogger.UNIDENTIFIED; + } + + // "normalize" the "auditRequestType" + if (auditRequestType != null) { + auditRequestType = auditRequestType.trim(); + } else { + auditRequestType = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + // "normalize" the "auditRequesterID" + if (auditRequesterID != null) { + auditRequesterID = auditRequesterID.trim(); + } else { + auditRequesterID = ILogger.UNIDENTIFIED; + } + + IPKIMessage replymsg = null; + + try { + IRequest r = null; + IRequestQueue queue = mAuthority.getRequestQueue(); + String srcid = source + ":" + msg.getReqId(); + + // find request in request queue and return result. + RequestId thisreqid = queue.findRequestBySourceId(srcid); + IRequest thisreq = null; + + if (thisreqid != null) { + thisreq = queue.findRequest(thisreqid); + if (thisreq == null) { + // strange case. + String errormsg = "Cannot find request in request queue " + + thisreqid; + + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage( + "CMSGW_REQUEST_ID_NOT_FOUND_1", + thisreqid.toString())); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // does not yet matter at this point! + + throw new EBaseException(errormsg); + } else { + mAuthority.log(ILogger.LL_INFO, + "Found request " + thisreqid + " for " + srcid); + replymsg = CMS.getHttpPKIMessage(); + replymsg.fromRequest(thisreq); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // does not yet matter at this point! + + return replymsg; + } + } + + // if not found process request. + thisreq = queue.newRequest(msg.getReqType()); + CMS.debug("ConnectorServlet: created requestId=" + + thisreq.getRequestId().toString()); + thisreq.setSourceId(srcid); + + // NOTE: For the following signed audit message, since we only + // care about the "msg.toRequest( thisreq );" command, and + // since this command does not throw an EBaseException + // (which is the only exception designated by this method), + // then this code does NOT need to be contained within its + // own special try/catch block. + msg.toRequest( thisreq ); + + if( isProfileRequest( thisreq ) ) { + X509CertInfo info = + thisreq.getExtDataInCertInfo( + IEnrollProfile.REQUEST_CERTINFO ); + + try { + CertificateSubjectName sn = ( CertificateSubjectName ) + info.get( X509CertInfo.SUBJECT ); + + // if the cert subject name is NOT MISSING, retrieve the + // actual "auditCertificateSubjectName" and "normalize" + // it + if( sn != null ) { + subject = sn.toString(); + if( subject != null ) { + // NOTE: This is ok even if the cert subject + // name is "" (empty)! + auditCertificateSubjectName = subject.trim(); + } + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + auditProfileID(), + auditCertificateSubjectName ); + + audit( auditMessage ); + } catch( CertificateException e ) { + CMS.debug( "ConnectorServlet: processRequest " + + e.toString() ); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditProfileID(), + auditCertificateSubjectName ); + + audit( auditMessage ); + } catch( IOException e ) { + CMS.debug( "ConnectorServlet: processRequest " + + e.toString() ); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + auditProfileID(), + auditCertificateSubjectName ); + + audit( auditMessage ); + } + } + + thisreq.setExtData(IRequest.AUTH_TOKEN, token); + + // setting requestor type must come after copy contents. because + // requestor is a regular attribute. + thisreq.setExtData(IRequest.REQUESTOR_TYPE, + IRequest.REQUESTOR_RA); + mAuthority.log(ILogger.LL_INFO, "Processing remote request " + + srcid); + + // Set this so that request's updateBy is recorded + SessionContext s = SessionContext.getContext(); + + if (s.get(SessionContext.USER_ID) == null) { + s.put(SessionContext.USER_ID, sourceUserId); + } + + if (s.get(SessionContext.REQUESTER_ID) == null) { + s.put(SessionContext.REQUESTER_ID, msg.getReqId()); + } + + CMS.debug("ConnectorServlet: calling processRequest instance=" + + thisreq); + if (isProfileRequest(thisreq)) { + normalizeProfileRequest(thisreq); + } + + try { + queue.processRequest( thisreq ); + + if( isProfileRequest( thisreq ) ) { + // reset the "auditInfoCertValue" + auditInfoCertValue = auditInfoCertValue( thisreq ); + + if( auditInfoCertValue != null ) { + if( !( auditInfoCertValue.equals( + ILogger.SIGNED_AUDIT_EMPTY_VALUE ) ) ) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue ); + + audit( auditMessage ); + } + } + } + } catch( EBaseException eAudit1 ) { + if( isProfileRequest( thisreq ) ) { + // reset the "auditInfoCertValue" + auditInfoCertValue = auditInfoCertValue( thisreq ); + + if( auditInfoCertValue != null ) { + if( !( auditInfoCertValue.equals( + ILogger.SIGNED_AUDIT_EMPTY_VALUE ) ) ) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue ); + + audit( auditMessage ); + } + } + } + + // rethrow EBaseException to primary catch clause + // within this method + throw eAudit1; + } + + replymsg = CMS.getHttpPKIMessage(); + replymsg.fromRequest(thisreq); + + CMS.debug("ConnectorServlet: replymsg.reqStatus=" + + replymsg.getReqStatus()); + + //for audit log + String agentID = sourceUserId; + String initiative = AuditFormat.FROMRA + " trustedManagerID: " + + agentID + " remote reqID " + msg.getReqId(); + String authMgr = AuditFormat.NOAUTH; + + if (token != null) { + authMgr = + token.getInString(AuthToken.TOKEN_AUTHMGR_INST_NAME); + } + + if (isProfileRequest(thisreq)) { + // XXX audit log + CMS.debug("ConnectorServlet: done requestId=" + + thisreq.getRequestId().toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // has already been logged at this point! + + return replymsg; + } + + // Get the certificate info from the request + X509CertInfo x509Info[] = thisreq.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + try { + if (!thisreq.getRequestStatus().equals(RequestStatus.COMPLETE)) { + if (x509Info != null) { + for (int i = 0; i < x509Info.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + thisreq.getRequestStatus(), + x509Info[i].get(X509CertInfo.SUBJECT), + ""} + ); + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + thisreq.getRequestStatus()} + ); + } + } else { + if (thisreq.getRequestType().equals(IRequest.ENROLLMENT_REQUEST)) { + // XXX make the repeat record. + // Get the certificate(s) from the request + X509CertImpl x509Certs[] = null; + + if (x509Info != null) + x509Certs = + thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + // return potentially more than one certificates. + if (x509Certs != null) { + for (int i = 0; i < x509Certs.length; i++) { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.FORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed", + x509Certs[i].getSubjectDN(), + "cert issued serial number: 0x" + + x509Certs[i].getSerialNumber().toString(16)} + ); + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed"} + ); + } + } else if (thisreq.getRequestType().equals(IRequest.RENEWAL_REQUEST)) { + X509CertImpl[] certs = + thisreq.getExtDataInCertArray(IRequest.OLD_CERTS); + X509CertImpl old_cert = certs[0]; + + certs = thisreq.getExtDataInCertArray(IRequest.ISSUED_CERTS); + X509CertImpl renewed_cert = certs[0]; + + if (old_cert != null && renewed_cert != null) { + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.RENEWALFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative, + authMgr, + "completed", + old_cert.getSubjectDN(), + old_cert.getSerialNumber().toString(16), + "new serial number: 0x" + + renewed_cert.getSerialNumber().toString(16)} + ); + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed with error"} + ); + } + } else if (thisreq.getRequestType().equals(IRequest.REVOCATION_REQUEST)) { + Certificate[] oldCerts = + thisreq.getExtDataInCertArray(IRequest.OLD_CERTS); + RevokedCertImpl crlentries[] = + thisreq.getExtDataInRevokedCertArray(IRequest.REVOKED_CERTS); + CRLExtensions crlExts = crlentries[0].getExtensions(); + int reason = 0; + + if (crlExts != null) { + Enumeration enum1 = crlExts.getElements(); + + while (enum1.hasMoreElements()) { + Extension ext = (Extension) enum1.nextElement(); + + if (ext instanceof CRLReasonExtension) { + reason = ((CRLReasonExtension) ext).getReason().toInt(); + break; + } + } + } + + int count = oldCerts.length; + Integer result = thisreq.getExtDataInInteger(IRequest.RESULT); + + if (result.equals(IRequest.RES_ERROR)) { + String[] svcErrors = + thisreq.getExtDataInStringArray(IRequest.SVCERRORS); + + if (svcErrors != null && svcErrors.length > 0) { + for (int i = 0; i < svcErrors.length; i++) { + String err = svcErrors[i]; + + if (err != null) { + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative, + "completed with error: " + + err, + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString()} + ); + } + } + } + } + } + } + } else { + // the success. + for (int j = 0; j < count; j++) { + if (oldCerts[j] != null) { + if (oldCerts[j] instanceof X509CertImpl) { + X509CertImpl cert = (X509CertImpl) oldCerts[j]; + + mLogger.log(ILogger.EV_AUDIT, ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.DOREVOKEFORMAT, + new Object[] { + thisreq.getRequestId(), + initiative, + "completed", + cert.getSubjectDN(), + cert.getSerialNumber().toString(16), + RevocationReason.fromInt(reason).toString()} + ); + } + } + } + } + } else { + mLogger.log(ILogger.EV_AUDIT, + ILogger.S_OTHER, + AuditFormat.LEVEL, + AuditFormat.NODNFORMAT, + new Object[] { + thisreq.getRequestType(), + thisreq.getRequestId(), + initiative, + authMgr, + "completed"} + ); + } + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.SUCCESS, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } catch (IOException e) { + CMS.debug("ConnectorServlet: process " + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } catch (CertificateException e) { + CMS.debug("ConnectorServlet: process " + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } catch (Exception e) { + CMS.debug("ConnectorServlet: process " + e.toString()); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + } finally { + SessionContext.releaseContext(); + } + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // has already been logged at this point! + + return replymsg; + } catch (EBaseException e) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_INTER_BOUNDARY_SUCCESS, + auditSubjectID, + ILogger.FAILURE, + auditProtectionMethod, + auditRequestType, + auditRequesterID); + + audit(auditMessage); + + // NOTE: The signed audit event + // LOGGING_SIGNED_AUDIT_PROFILE_CERT_REQUEST + // has either already been logged, or + // does not yet matter at this point! + + return replymsg; + } + } + + protected X509Certificate + getPeerCert(HttpServletRequest req) throws EBaseException { + return getSSLClientCertificate(req); + } + + public String getServletInfo() { + return INFO; + } + + /** + * Signed Audit Log + * + * This method is inherited by all extended "CMSServlet"s, + * and is called to store messages to the signed audit log. + * <P> + * + * @param msg signed audit log message + */ + protected void audit(String msg) { + // in this case, do NOT strip preceding/trailing whitespace + // from passed-in String parameters + + if (mSignedAuditLogger == null) { + return; + } + + mSignedAuditLogger.log(ILogger.EV_SIGNED_AUDIT, + null, + ILogger.S_SIGNED_AUDIT, + ILogger.LL_SECURITY, + msg); + } + + /** + * Signed Audit Log Profile ID + * + * This method is inherited by all extended "EnrollProfile"s, + * and is called to obtain the "ProfileID" for + * a signed audit log message. + * <P> + * + * @return id string containing the signed audit log message ProfileID + */ + protected String auditProfileID() { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + String profileID = getId(); + + if (profileID != null) { + profileID = profileID.trim(); + } else { + profileID = ILogger.UNIDENTIFIED; + } + + return profileID; + } + + /** + * Signed Audit Log Info Certificate Value + * + * This method is called to obtain the certificate from the passed in + * "X509CertImpl" for a signed audit log message. + * <P> + * + * @param request a Request containing an X509CertImpl + * @return cert string containing the certificate + */ + private String auditInfoCertValue(IRequest request) { + // if no signed audit object exists, bail + if (mSignedAuditLogger == null) { + return null; + } + + X509CertImpl x509cert = request.getExtDataInCert( + IEnrollProfile.REQUEST_ISSUED_CERT); + + if (x509cert == null) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + byte rawData[] = null; + + try { + rawData = x509cert.getEncoded(); + } catch (CertificateEncodingException e) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + + String cert = null; + + // convert "rawData" into "base64Data" + if (rawData != null) { + String base64Data = null; + + base64Data = com.netscape.osutil.OSUtil.BtoA(rawData).trim(); + + StringBuffer sb = new StringBuffer(); + // extract all line separators from the "base64Data" + for (int i = 0; i < base64Data.length(); i++) { + if (base64Data.substring(i, i).getBytes() != EOL) { + sb.append(base64Data.substring(i, i)); + } + } + cert = sb.toString(); + } + + if (cert != null) { + cert = cert.trim(); + + if (cert.equals("")) { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } else { + return cert; + } + } else { + return ILogger.SIGNED_AUDIT_EMPTY_VALUE; + } + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java b/pki/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java new file mode 100644 index 000000000..34004767e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/connector/GenerateKeyPairServlet.java @@ -0,0 +1,294 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.connector; + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import javax.servlet.*; +import javax.servlet.http.*; + +import java.io.*; + +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + + +/** + * GenerateKeyPairServlet + * handles "server-side key pair generation" requests from the + * netkey RA. + * + * @author Christina Fu (cfu) + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +//XXX add auditing later +public class GenerateKeyPairServlet extends CMSServlet { + + 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; + + IConfigStore sconfig = CMS.getConfigStore(); + 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"; + } + + String selectedToken = null; + + 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, "read"); + } 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 { + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + super.service(req, resp); + + + } + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java b/pki/base/common/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.java new file mode 100644 index 000000000..1a3c2ed1c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/connector/TokenKeyRecoveryServlet.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.connector; + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import javax.servlet.*; +import javax.servlet.http.*; + +import java.io.*; + +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * TokenKeyRecoveryServlet + * handles "key recovery service" requests from the + * netkey TPS + * + * @author Christina Fu (cfu) + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +//XXX add auditing later +public class TokenKeyRecoveryServlet extends CMSServlet { + + 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; + } + + String selectedToken = null; + + 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 outputString = ""; + String wrappedPrivKeyString = ""; + String publicKeyString = ""; + /* 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"); + + /* + 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); + 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, "read"); + } 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 + + } + + /** XXX remember to check 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 { + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + super.service(req, resp); + + + } + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/AdminAuthenticatePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AdminAuthenticatePanel.java new file mode 100644 index 000000000..295c163cf --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AdminAuthenticatePanel.java @@ -0,0 +1,320 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import java.io.*; +import java.net.URL; +import com.netscape.certsrv.base.*; +import java.util.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; + +import com.netscape.cms.servlet.wizard.*; + +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 { + boolean done = cs.getBoolean("preop.AdminAuthenticate.done"); + 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.httpsport"); + } 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("preop.cert."); + c1.append(t1); + c1.append(".nickname,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".dn,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".keytype,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".privkey.id,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".pubkey.exponent,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".pubkey.modulus"); + + 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"); + } + + String content = "uid="+uid+"&pwd="+pwd+"&op=get&names=preop.module.token,instanceId,internaldb.basedn,internaldb.ldapauth.password,internaldb.ldapconn.host,internaldb.ldapconn.port,internaldb.ldapauth.bindDN"+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", ""); + CryptoToken tok = cm.getTokenByName(tokenname); + CryptoStore store = tok.getCryptoStore(); + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/AdminPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AdminPanel.java new file mode 100644 index 000000000..cea666245 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AdminPanel.java @@ -0,0 +1,666 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.cmsutil.crypto.*; +import com.netscape.cmsutil.http.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.ca.*; +import java.io.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +import java.net.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.util.*; +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import com.netscape.cmsutil.xml.*; +import org.xml.sax.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.pkix.crmf.*; + +import com.netscape.cms.servlet.wizard.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.dbs.certdb.*; + +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 = ""; + String clone = ""; + context.put("import", "true"); + + try { + type = cs.getString("preop.ca.type", ""); + String subsystemtype = cs.getString("cs.type", ""); + clone = cs.getString("preop.subsystem.select", ""); + context.put("clone", clone); + } 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("preop.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 + { + IConfigStore config = CMS.getConfigStore(); + try { + String s = config.getString("preop.subsystem.select", ""); + context.put("clone", s); + if (s.equals("clone")) + return; + } catch (Exception e) { + } + + 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("")) + throw new IOException("Name is empty"); + + if (email == null || email.equals("")) + throw new IOException("Email is empty"); + + if (uid == null || uid.equals("")) + throw new IOException("Uid is empty"); + + if (!pwd.equals(pwd_again)) { + throw new IOException("Password and password again are not the same."); + } + + if (email == null || email.length() == 0) { + 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 = ""; + try { + type = config.getString(PRE_CA_TYPE, ""); + String subsystemtype = config.getString("cs.type", ""); + } catch (Exception e) {} + + String select = ""; + try { + select = config.getString("preop.subsystem.select", ""); + context.put("clone", select); + if (select.equals("clone")) { + return; + } + } 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); + String pwd = HttpInput.getPassword(request, "__pwd"); + + 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."); + throw e; + } + + if (ca != null) { + CMS.debug("AdminPanel update: this is 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."); + throw e; + } + } else { + String ca_hostname = null; + int ca_port = -1; + + 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("preop.securitydomain.host", ""); + ca_port = config.getInteger("preop.securitydomain.httpsport"); + } 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) {} + + } + + private void createAdmin(HttpServletRequest request) throws IOException { + IUGSubsystem system = (IUGSubsystem) (CMS.getSubsystem(IUGSubsystem.ID)); + IConfigStore config = CMS.getConfigStore(); + String adminName = null; + String groupName = null; + + try { + adminName = config.getString(PRE_CONF_ADMIN_NAME, + "Certificate System Administrator"); + 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("preop.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 sd_hostname = null; + int sd_port = -1; + + try { + sd_hostname = config.getString("preop.securitydomain.host", ""); + sd_port = config.getInteger("preop.securitydomain.httpsport"); + } catch (Exception e) {} + + 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); + + 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 = ""; + + String clone = ""; + try { + + clone = cs.getString("preop.subsystem.select", ""); + 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("clone", clone); + 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")); + } + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/AgentAuthenticatePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AgentAuthenticatePanel.java new file mode 100644 index 000000000..539ffd6c4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AgentAuthenticatePanel.java @@ -0,0 +1,225 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.property.*; +import java.io.*; +import java.net.URL; +import com.netscape.certsrv.base.*; +import java.util.*; + +import com.netscape.cms.servlet.wizard.*; + +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("preop.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"); + } + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java new file mode 100644 index 000000000..6f912d725 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/AuthenticatePanel.java @@ -0,0 +1,193 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.property.*; +import java.io.*; +import java.net.URL; +import com.netscape.certsrv.base.*; +import java.util.*; + +import com.netscape.cms.servlet.wizard.*; + +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/pki/base/common/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java new file mode 100644 index 000000000..5c5d80719 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/BackupKeyCertPanel.java @@ -0,0 +1,427 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import org.mozilla.jss.util.Password; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import java.io.*; +import java.net.URL; +import com.netscape.certsrv.base.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +import java.security.KeyPair; +import netscape.security.util.*; +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import org.mozilla.jss.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkcs12.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.crypto.PrivateKey; +import com.netscape.cmsutil.crypto.*; + +import com.netscape.cms.servlet.wizard.*; + +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 { + boolean done = cs.getBoolean("preop.backupkeycert.done"); + 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"); + throw new IOException("PK12 password is empty."); + } + + if (!pwd.equals(pwdAgain)) { + CMS.debug("BackupKeyCertPanel validate: Password and password again are not the same."); + 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) { + } + } + + /** + * 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 { + byte[] localKeyId = 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/BaseServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/BaseServlet.java new file mode 100644 index 000000000..69dc7910e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/BaseServlet.java @@ -0,0 +1,93 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + +import java.io.*; +import java.util.*; +import com.netscape.certsrv.apps.*; + + +public class BaseServlet extends VelocityServlet { + + /** + * 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("CMSServlet:serice() uri = " + httpReq.getRequestURI()); + Enumeration paramNames = httpReq.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String pn = (String) paramNames.nextElement(); + + CMS.debug( + "CMSServlet::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/pki/base/common/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.java new file mode 100644 index 000000000..1cf6d7421 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CAInfoPanel.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 org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import org.xml.sax.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.crypto.*; +import java.io.*; +import java.util.*; +import java.net.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import com.netscape.cmsutil.http.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.asn1.*; + +import com.netscape.cms.servlet.wizard.*; + +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 sdcaHostname = ""; + String sdcaHttpPort = ""; + String othercaHostname = ""; + String othercaPort = ""; + 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"; + +/* + try { + cstype = cs.getString("cs.type", ""); + } catch (EBaseException e) {} +*/ + + CMS.debug("CAInfoPanel: Ready to get url"); + Vector v = getUrlListFromSecurityDomain(cs, cstype); + 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 { + IConfigStore config = CMS.getConfigStore(); + } + + /** + * 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 - http://...) + 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 httpPortStr) throws IOException { + CMS.debug("CAInfoPanel update: this is the CA in the security domain."); + IConfigStore config = CMS.getConfigStore(); + + context.put("sdcaHostname", hostname); + context.put("sdHttpPort", httpPortStr); + + if (hostname == null || hostname.length() == 0) { + context.put("errorString", "Hostname is null"); + throw new IOException("Hostname is null"); + } + + int httpport = -1; + + try { + httpport = Integer.parseInt(httpPortStr); + } catch (Exception e) { + CMS.debug( + "CAInfoPanel update: Http 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", httpPortStr); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + updateCertChain(config, "ca", hostname, httpport, 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/Cert.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/Cert.java new file mode 100644 index 000000000..4de73d2da --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/Cert.java @@ -0,0 +1,162 @@ +// --- 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.StringTokenizer; +import java.util.Vector; + + +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 boolean mEnable = true; + 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 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; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertPrettyPrintPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertPrettyPrintPanel.java new file mode 100644 index 000000000..bd4893915 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertPrettyPrintPanel.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.csadmin; + + +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.*; +import java.security.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cmsutil.crypto.*; + +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.pkcs11.*; + +import netscape.security.util.*; +import netscape.security.pkcs.*; +import netscape.security.x509.*; + +import com.netscape.cms.servlet.wizard.*; + +public class CertPrettyPrintPanel extends WizardPanelBase { + private Vector 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(); + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java new file mode 100644 index 000000000..10b9b55fb --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertRequestPanel.java @@ -0,0 +1,722 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import java.util.*; +import java.io.*; +import java.security.*; +import java.math.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cmsutil.crypto.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.*; + +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.PrivateKey; +import org.mozilla.jss.pkcs11.*; + +import netscape.security.util.*; +import netscape.security.pkcs.*; +import netscape.security.x509.*; + +import com.netscape.cms.servlet.wizard.*; + +public class CertRequestPanel extends WizardPanelBase { + private Vector 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 { + boolean done = cs.getBoolean("preop.CertRequestPanel.done"); + return true; + } catch (Exception ee) { + if (hardware) { + CMS.debug("CertRequestPanel findCertificate: The certificate with the same nickname has been found on HSM. Please remove it before proceeding."); + throw new IOException("The certificate with the same nickname 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 select = ""; + String list = ""; + String tokenname = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + 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)); + } 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 { + boolean done = cs.getBoolean("preop.CertRequestPanel.done"); + 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"); + 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); + + 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(); + + 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 nickname = cs.getString("preop.cert.sslserver.nickname", ""); + 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 nickname = cs.getString("preop.cert.sslserver.nickname", ""); + 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(); + + String catype = ""; + try { + catype = config.getString("preop.ca.type", ""); + } catch (Exception e) { + } + + if (isPanelDone()) + return; + + try { + Enumeration 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; + + 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: Failed to import certificate " + + certTag + " Exception: " + + ee.toString()); + } + } + } 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)) { + CMS.debug("CertRequestPanel: cert might not have contained chain...calling importCertificateChain"); + 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: Failed to import certificate " + + certTag + " Exception: " + + ee.toString()); + } + } else { + CMS.debug("CertRequestPanel: in update() input null"); + } + } + } 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()); + } + } + + 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); + ic.setObjectSigningTrust(InternalCertificate.USER); + } + } + } catch (Exception e) { + } + } + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java new file mode 100644 index 000000000..ca1a65bd4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CertUtil.java @@ -0,0 +1,453 @@ +// --- 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.security.*; +import java.security.cert.*; +import java.net.*; +import java.util.*; +import java.math.*; +import java.io.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cmsutil.crypto.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.cmsutil.http.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.usrgrp.*; +import netscape.security.x509.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.crypto.PrivateKey; +import com.netscape.cmsutil.xml.*; +import org.mozilla.jss.crypto.KeyPairGenerator; +import netscape.security.pkcs.*; +import netscape.ldap.*; +import org.apache.velocity.context.Context; +import org.xml.sax.*; + + +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; + 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"); + 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); + 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()); + } + } + + 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; + + try { + String dn = config.getString(prefix + certTag + ".dn"); + Date date = new Date(); + + X509CertInfo info = null; + + 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); + } 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); + } + CMS.debug("Cert Template: " + info.toString()); + + String instanceRoot = config.getString("instanceRoot"); + + CertInfoProfile processor = new CertInfoProfile( + instanceRoot + "/conf/" + profile); + + processor.populate(info); + + String caPriKeyID = config.getString( + prefix + "signing" + ".privkey.id"); + org.mozilla.jss.crypto.PrivateKey caPrik = CryptoUtil.findPrivateKeyFromID( + CryptoUtil.string2byte(caPriKeyID)); + + 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"); + CMS.debug("CA Signing Key type " + caSigningKeyType); + if (caSigningKeyType.equals("ecc")) { + CMS.debug("Signing ECC certificate"); + cert = CryptoUtil.signECCCert(caPrik, info); + } else { + CMS.debug("Signing RSA certificate"); + cert = CryptoUtil.signCert(caPrik, info, + SignatureAlgorithm.RSASignatureWithSHA1Digest); + } + + 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 = (ICertRecord) cr.createCertRecord( + cert.getSerialNumber(), cert, null); + + 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()); + } + } + + 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"); + int index = 0; + + 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; + + boolean hardware = false; + if (!tokenname.equals("internal") && !tokenname.equals("Internal Key Storage Token")) { + hardware = true; + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java new file mode 100644 index 000000000..829e46a44 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CheckIdentity.java @@ -0,0 +1,115 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; + + +public class CheckIdentity extends CMSServlet { + + 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 { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + IAuthToken authToken = null; + + try { + authToken = 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigBaseServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigBaseServlet.java new file mode 100644 index 000000000..61a8a98a6 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigBaseServlet.java @@ -0,0 +1,96 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + +import java.io.*; +import java.util.*; +import com.netscape.certsrv.apps.*; + + +public abstract class ConfigBaseServlet extends BaseServlet { + 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("CMSServlet:serice() uri = " + httpReq.getRequestURI()); + Enumeration paramNames = httpReq.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String pn = (String) paramNames.nextElement(); + + CMS.debug( + "CMSServlet::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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java new file mode 100644 index 000000000..6acb71273 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertApprovalCallback.java @@ -0,0 +1,37 @@ +// --- 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.*; +import com.netscape.certsrv.apps.CMS; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.ssl.*; + + +public class ConfigCertApprovalCallback + implements SSLCertificateApprovalCallback { + + public ConfigCertApprovalCallback() { + } + + public boolean approve(X509Certificate cert, + SSLCertificateApprovalCallback.ValidityStatus status) { + return true; + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertReqServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertReqServlet.java new file mode 100644 index 000000000..0a9d9a9cd --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCertReqServlet.java @@ -0,0 +1,46 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + + +public class ConfigCertReqServlet extends BaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCloneServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCloneServlet.java new file mode 100644 index 000000000..73150946b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigCloneServlet.java @@ -0,0 +1,46 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + + +public class ConfigCloneServlet extends BaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigDatabaseServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigDatabaseServlet.java new file mode 100644 index 000000000..b944fde7c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigDatabaseServlet.java @@ -0,0 +1,190 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import java.io.*; + + +public class ConfigDatabaseServlet extends ConfigBaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.java new file mode 100644 index 000000000..29f5fa284 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMLoginPanel.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 org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; +import javax.servlet.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.property.*; +import com.netscape.cmsutil.crypto.*; +import java.util.*; +import java.io.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.util.Password; +import org.mozilla.jss.util.PasswordCallback; +import org.mozilla.jss.util.IncorrectPasswordException; +import com.netscape.cmsutil.password.*; + +import com.netscape.cms.servlet.wizard.*; + +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; + try { + tokName = HttpInput.getTokenName(request, "SecToken"); + } catch (IOException e) { + } + + 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()); + + if (password != null) { + 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; + } + } else { // no password in password file, get from user + CMS.debug( + "ConfigHSMLoginPanel: loginToken():no password in cache, getting from user"); + 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) { + + IConfigStore cs = CMS.getConfigStore(); + String select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + +// if (select.equals("clone")) + // return; + + 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"); + 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("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", ""); + + } + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMServlet.java new file mode 100644 index 000000000..536dfe770 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigHSMServlet.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.csadmin; + + +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; +import javax.servlet.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cmsutil.crypto.*; +import java.util.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkcs11.*; + + +public class ConfigHSMServlet extends ConfigBaseServlet { + private CryptoManager mCryptoManager = null; + private Vector mSupportedModules = null; + private Vector mOtherModules = null; + private String mDefaultTok = null; + private Hashtable mCurrModTable = new Hashtable(); + + public void init(ServletConfig config) throws ServletException { + super.init(config); + } + + public void loadCurrModTable() { + try { + // getting existing modules + mCryptoManager = CryptoManager.getInstance(); + Enumeration modules = mCryptoManager.getModules(); + + while (modules.hasMoreElements()) { + PK11Module mod = (PK11Module) 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 m = mCurrModTable.elements(); + + mOtherModules = new Vector(); + while (m.hasMoreElements()) { + PK11Module mod = (PK11Module) m.nextElement(); + Enumeration s = mSupportedModules.elements(); + boolean found = false; + + while (s.hasMoreElements()) { + Module sm = (Module) 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((Object) module); + break; + } + }// while + } + + /* + * find all tokens belonging to a module and load the Module + */ + public void loadModTokens(Module module, PK11Module mod) { + Enumeration tokens = mod.getTokens(); + + while (tokens.hasMoreElements()) { + try { + CryptoToken token = (CryptoToken) 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(); + // 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 = (PK11Module) mCurrModTable.get(cn); + + loadModTokens(module, m); + } + + CMS.debug("ConfigHSMServlet: adding module " + cn); + // add module to set + if (!mSupportedModules.contains(module)) { + mSupportedModules.addElement((Object) 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigImportCertServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigImportCertServlet.java new file mode 100644 index 000000000..892d24584 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigImportCertServlet.java @@ -0,0 +1,46 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + + +public class ConfigImportCertServlet extends BaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigJoinServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigJoinServlet.java new file mode 100644 index 000000000..f1a1a584c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigJoinServlet.java @@ -0,0 +1,185 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.profile.*; +import com.netscape.cmsutil.crypto.*; + +import netscape.security.pkcs.*; +import netscape.security.x509.*; + +import java.util.*; +import java.io.*; + +import java.security.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.KeyPairGenerator; + + +public class ConfigJoinServlet extends ConfigBaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigRootCAServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigRootCAServlet.java new file mode 100644 index 000000000..e07ea3c3b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ConfigRootCAServlet.java @@ -0,0 +1,135 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.profile.*; + +import java.util.*; + + +public class ConfigRootCAServlet extends ConfigBaseServlet { + + 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 getProfiles() { + IConfigStore config = CMS.getConfigStore(); + String instancePath = ""; + + try { + instancePath = config.getString("instanceRoot"); + } catch (EBaseException e) {} + String p[] = { "caCert.profile" }; + Vector profiles = new Vector(); + + 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 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 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java new file mode 100644 index 000000000..5fccf9004 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/CreateSubsystemPanel.java @@ -0,0 +1,286 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import org.mozilla.jss.crypto.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.base.*; +import com.netscape.cmsutil.crypto.*; +import java.net.*; +import java.io.*; +import java.util.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.xml.sax.*; + +import com.netscape.cms.servlet.wizard.*; + +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", ""); + } + + 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 = ""; + String url = ""; + + 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("https_port", CMS.getEESSLPort()); + context.put("http_port", CMS.getEENonSSLPort()); + } catch (EBaseException e) { + } + + Vector v = getMasterUrlListFromSecurityDomain(config, cstype); + 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"); + 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"); + 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"); + + 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; + } + } + } catch (Exception e) { + } + + url = url.substring(url.indexOf("http")); + + URL u = new URL(url); + String host = u.getHost(); + int port = u.getPort(); + + config.putString("preop.master.hostname", host); + config.putInteger("preop.master.httpsport", port); + + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + if (cstype.equals("ca")) { + updateCertChain(config, "clone", host, port, true, context, + certApprovalCallback); + } + + getTokenInfo(config, cstype, host, port, true, context, + certApprovalCallback); + } else { + CMS.debug("CreateSubsystemPanel: invalid choice " + select); + errorString = "Invalid choice"; + throw new IOException("invalid choice " + select); + } + + try { + config.commit(false); + } catch (EBaseException e) { + } + + context.put("errorString", errorString); + } + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.java new file mode 100644 index 000000000..3b874b46d --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabasePanel.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.csadmin; + + +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.ca.*; +import java.io.*; +import java.util.*; +import com.netscape.cmsutil.ldap.*; + +import com.netscape.cms.servlet.wizard.*; + +public class DatabasePanel extends WizardPanelBase { + + 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 = "csRoot"; + private static final String MASTER_AGREEMENT = "masteragreement-"; + private static final String CLONE_AGREEMENT = "cloneagreement-"; + + 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"; + try { + String s = cs.getString("preop.database.removeData"); + } 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", ""); + errorString = cs.getString("preop.database.errorString", ""); + } catch (Exception e) { + CMS.debug("DatabasePanel display: " + e.toString()); + } + } else if (select.equals("clone")) { + hostname = 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("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")); + context.put("portStr", request.getParameter("port")); + context.put("basedn", request.getParameter("basedn")); + context.put("binddn", request.getParameter("binddn")); + context.put("bindpwd", request.getParameter("__bindpwd")); + context.put("database", request.getParameter("database")); + } + + /** + * 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 { + String s = cs.getString("preop.database.removeData"); + } catch (Exception e) { + context.put("firsttime", "true"); + } + + String hostname = HttpInput.getHostname(request, "host"); + context.put("hostname", hostname); + + String portStr = HttpInput.getPortNumber(request, "port"); + context.put("portStr", portStr); + + String basedn = HttpInput.getDN(request, "basedn"); + context.put("basedn", basedn); + + String binddn = HttpInput.getDN(request, "binddn"); + context.put("binddn", binddn); + + String database = HttpInput.getLdapDatabase(request, "database"); + context.put("database", database); + + String bindpwd = HttpInput.getPassword(request, "__bindpwd"); + context.put("bindpwd", bindpwd); + + String secure = HttpInput.getCheckbox(request, "secureConn"); + context.put("secureConn", secure); + + String select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + if (select.equals("clone")) { + String masterhost = ""; + String masterport = ""; + String masterbasedn = ""; + try { + masterhost = cs.getString("preop.internaldb.master.hostname", ""); + masterport = cs.getString("preop.internaldb.master.port", ""); + masterbasedn = cs.getString("preop.internaldb.master.basedn", ""); + } catch (Exception e) { + } + + //get the real host name + String realhostname = ""; + if (hostname.equals("localhost")) { + try { + realhostname = cs.getString("machineName", ""); + } catch (Exception ee) { + } + } + 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"); + } + + if (hostname == null || hostname.length() == 0) { + cs.putString("preop.database.errorString", "Host is empty string"); + throw new IOException("Host is empty string"); + } + + if (portStr != null && portStr.length() > 0) { + int port = -1; + + try { + port = Integer.parseInt(portStr); + } catch (Exception e) { + cs.putString("preop.database.errorString", "Port is invalid"); + throw new IOException("Port is invalid"); + } + } else { + cs.putString("preop.database.errorString", "Port is empty string"); + throw new IOException("Port is empty string"); + } + + if (basedn == null || basedn.length() == 0) { + cs.putString("preop.database.errorString", "Base DN is empty string"); + throw new IOException("Base DN is empty string"); + } + + if (binddn == null || binddn.length() == 0) { + cs.putString("preop.database.errorString", "Bind DN is empty string"); + throw new IOException("Bind DN is empty string"); + } + + if (database == null || database.length() == 0) { + cs.putString("preop.database.errorString", + "Database is empty string"); + throw new IOException("Database is empty string"); + } + + if (bindpwd == null || bindpwd.length() == 0) { + cs.putString("preop.database.errorString", + "Bind password is empty string"); + throw new IOException("Bind password is empty string"); + } + + 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 void populateDB(HttpServletRequest request, Context context, String secure) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + + String baseDN = ""; + + try { + baseDN = cs.getString("internaldb.basedn"); + } catch (Exception e) { + CMS.debug("DatabasePanel populateDB: " + e.toString()); + throw new IOException( + "Failed to retrieve LDAP information from CS.cfg."); + } + + LDAPConnection conn = getLocalLDAPConn(context, secure); + + try { + LDAPEntry entry = conn.read(baseDN); + if (entry != null) { + CMS.debug("DatabasePanel update: This base DN has already been used."); + throw new IOException("This base DN ("+baseDN+") has already been used."); + } + } catch (LDAPException e) { + CMS.debug("DatabasePanel update: Exception="+e.toString()); + } + + // create database + String dn = ""; + String database = ""; + try { + database = cs.getString("internaldb.database", ""); + 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 (LDAPException e) { + if (e.getLDAPResultCode() == 68) { + CMS.debug("This database has already been used."); + throw new IOException("This database ("+dn+") has already been used."); + } + } 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 (LDAPException e) { + if (e.getLDAPResultCode() == 68) { + CMS.debug("This database has already been used."); + throw new IOException("This database ("+dn+") has already been used."); + } + } catch (Exception e) { + CMS.debug("Warning: database creation error - " + e.toString()); + throw new IOException("Failed to create the database."); + } + + try { + // create base dn + 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 (LDAPException e) { + if (e.getLDAPResultCode() == 68) { + CMS.debug("DatabasePanel: the baseDN has already been used."); + throw new IOException("This baseDN: "+baseDN+" has been used."); + } + } catch (Exception e) { + CMS.debug("Warning: suffix creation error - " + e.toString()); + throw new IOException("Failed to create the base DN: "+baseDN); + } + + // check if base DN is already being used + CMS.debug("DatabasePanel checking existing cn=ClonedSubsystems, ou=groups," + baseDN); + try { + LDAPEntry entry = conn.read("cn=ClonedSubsystems, ou=groups," + baseDN); + + if (entry != null) { + String remove = HttpInput.getID(request, "removeData"); + if (remove == null) + throw new IOException( + "Another instance is using this base DN " + baseDN); + else { + CMS.debug("Will remove the existing data from the base DN"); + String[] entries={"cn=Directory Administrators,"+baseDN, + "ou=Groups,"+baseDN, "ou=People,"+baseDN, + "ou=Special Users,"+baseDN, + "cn=Accounting Managers, ou=groups,"+baseDN, + "cn=HR Managers, ou=groups,"+baseDN, + "cn=QA Managers, ou=groups,"+baseDN, + "cn=PD Managers, ou=groups,"+baseDN}; + String filter = "objectclass=*"; + LDAPSearchConstraints cons = null; + String[] attrs = null; + LDAPSearchResults res = conn.search(baseDN, 1, filter, + attrs, true, cons); + deleteEntries(res, conn, baseDN, entries); + } + } + } catch (LDAPException e) {} + + // check to see if the base dn exists + CMS.debug("DatabasePanel checking existing " + baseDN); + boolean foundBaseDN = false; + + 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) { + } + + importLDIFS("preop.internaldb.ldif", conn); + if (select.equals("clone")) { + // if this is clone, add index before replication + importLDIFS("preop.internaldb.index_ldif", conn); + } else { + // data will be replicated from the master to the clone + // so clone does not need the data + importLDIFS("preop.internaldb.data_ldif", conn); + importLDIFS("preop.internaldb.index_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 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); + } + 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); + } + + LDAPUtil.importLDIF(conn, filename); + } + } + + /** + * Commit parameter changes + */ + public void update(HttpServletRequest request, + HttpServletResponse response, + Context context) throws IOException { + IConfigStore cs = CMS.getConfigStore(); + boolean hasErr = false; + + boolean firsttime = false; + context.put("firsttime", "false"); + try { + String v = cs.getString("preop.database.removeData"); + } catch (Exception e) { + context.put("firsttime", "true"); + firsttime = true; + } + + String hostname1 = ""; + String portStr1 = ""; + String database1 = ""; + String basedn1 = ""; + + try { + hostname1 = cs.getString("internaldb.ldapconn.host", ""); + portStr1 = cs.getString("internaldb.ldapconn.port", ""); + database1 = cs.getString("internaldb.database", ""); + basedn1 = cs.getString("internaldb.basedn", ""); + } catch (Exception e) { + } + + String hostname2 = HttpInput.getHostname(request, "host"); + String portStr2 = HttpInput.getPortNumber(request, "port"); + String database2 = HttpInput.getLdapDatabase(request, "database"); + String basedn2 = HttpInput.getDN(request, "basedn"); + + cs.putString("internaldb.ldapconn.host", hostname2); + cs.putString("internaldb.ldapconn.port", portStr2); + cs.putString("internaldb.basedn", basedn2); + String binddn = HttpInput.getDN(request, "binddn"); + cs.putString("internaldb.ldapauth.bindDN", binddn); + cs.putString("internaldb.database", database2); + String secure = HttpInput.getCheckbox(request, "secureConn"); + cs.putString("internaldb.ldapconn.secureConn", (secure.equals("on")?"true":"false")); + 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)) { + 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()); + 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()); + throw new IOException(e.toString()); + } + + String bindpwd = HttpInput.getPassword(request, "__bindpwd"); + IConfigStore psStore = null; + String passwordFile = null; + + try { + passwordFile = cs.getString("passwordFile"); + psStore = CMS.createFileConfigStore(passwordFile); + } catch (Exception e) { + CMS.debug("ConfigDatabaseServlet update: " + e.toString()); + throw new IOException( e.toString() ); + } + psStore.putString("internaldb", bindpwd); + 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()); + throw new IOException(e.toString()); + } + + String select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + if (select.equals("clone")) { + CMS.debug("Start setting up replication."); + setupReplication(request, context, (secure.equals("on")?"true":"false")); + CMS.debug("Finish setting up replication."); + + try { + CMS.reinit(IDBSubsystem.SUB_ID); + CMS.reinit(IAuthSubsystem.ID); + CMS.reinit(IAuthzSubsystem.ID); + } 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 + */ + String wait_dn = cs.getString("preop.internaldb.wait_dn", ""); + if (!wait_dn.equals("")) { + LDAPEntry task = null; + do { + try { + CMS.debug("Checking wait_dn " + wait_dn); + task = conn.read(wait_dn, (String[])null); + if (task != null) { + Thread.sleep(1000); + } + } catch (LDAPException e) { + task = null; + } + } while (task != null); + CMS.debug("Done checking wait_dn " + wait_dn); + } + + conn.disconnect(); + CMS.debug("Done populating local indexes"); + } catch (Exception e) { + CMS.debug("Populating index failure - " + 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()); + } + } + } + + private void setupReplication(HttpServletRequest request, + Context context, String secure) throws IOException { + String bindpwd = HttpInput.getPassword(request, "__bindpwd"); + 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) { + } + + String master1_hostname = ""; + int master1_port = -1; + String master1_binddn = ""; + String master1_bindpwd = ""; + + try { + master1_hostname = cs.getString("preop.internaldb.master.hostname", ""); + master1_port = cs.getInteger("preop.internaldb.master.port", -1); + master1_binddn = cs.getString("preop.internaldb.master.binddn", ""); + master1_bindpwd = cs.getString("preop.internaldb.master.bindpwd", ""); + } catch (Exception e) { + } + + String master2_hostname = ""; + int master2_port = -1; + String master2_binddn = ""; + String master2_bindpwd = ""; + + try { + master2_hostname = cs.getString("internaldb.ldapconn.host", ""); + master2_port = cs.getInteger("internaldb.ldapconn.port", -1); + master2_binddn = cs.getString("internaldb.ldapauth.bindDN", ""); + master2_bindpwd = bindpwd; + } catch (Exception e) { + } + + LDAPConnection conn1 = null; + LDAPConnection conn2 = null; + if (secure.equals("true")) { + CMS.debug("DatabasePanel setupReplication: creating secure (SSL) connections for internal ldap"); + conn1 = new LDAPConnection(CMS.getLdapJssSSLSocketFactory()); + conn2 = new LDAPConnection(CMS.getLdapJssSSLSocketFactory()); + } else { + CMS.debug("DatabasePanel setupreplication: creating non-secure (non-SSL) connections for internal ldap"); + conn1 = new LDAPConnection(); + conn2 = new LDAPConnection(); + } + + String basedn = ""; + try { + basedn = cs.getString("internaldb.basedn"); + } catch (Exception e) { + } + + try { + conn1.connect(master1_hostname, master1_port, master1_binddn, + master1_bindpwd); + conn2.connect(master2_hostname, master2_port, master2_binddn, + master2_bindpwd); + String suffix = cs.getString("internaldb.basedn", ""); + + String replicadn = "cn=replica,cn=\""+suffix+"\",cn=mapping tree,cn=config"; + CMS.debug("DatabasePanel setupReplication: replicadn="+replicadn); + + createReplicationManager(conn1, master1_bindpwd); + createReplicationManager(conn2, master2_bindpwd); + + String dir1 = getInstanceDir(conn1); + createChangeLog(conn1, dir1 + "/changelogs"); + + String dir2 = getInstanceDir(conn2); + createChangeLog(conn2, dir2 + "/changelogs"); + + enableReplication(replicadn, conn1, basedn, "1"); + enableReplication(replicadn, conn2, basedn, "2"); + + CMS.debug("DatabasePanel setupReplication: Finished enabling replication"); + + createReplicationAgreement(replicadn, conn1, masterAgreementName, + master2_hostname, master2_port, master2_bindpwd, basedn); + + createReplicationAgreement(replicadn, conn2, cloneAgreementName, + master1_hostname, master1_port, master1_bindpwd, basedn); + + // initialize consumer + initializeConsumer(replicadn, conn1, masterAgreementName); + + + // compare entries + compareAndWaitEntries(conn1, conn2, basedn); + + } catch (Exception e) { + CMS.debug("DatabasePanel setupReplication: "+e.toString()); + throw new IOException("Failed to setup the replication for cloning."); + } + } + + private void compareAndWaitEntries(LDAPConnection conn1, + LDAPConnection conn2, String basedn) + { + try { + LDAPSearchResults res = conn1.search(basedn, + LDAPConnection.SCOPE_ONE, "(objectclass=*)", null, true); + while (res.hasMoreElements()) { + LDAPEntry source = res.next(); + // check if this entry is present in conn2 + LDAPEntry dest = null; + do { + CMS.debug("DatabasePanel comparetAndWaitEntries checking " + + source.getDN()); + try { + dest = conn2.read(source.getDN(), (String[])null); + } catch (Exception e1) { + CMS.debug("DatabasePanel comparetAndWaitEntries " + + source.getDN() + " not found, let's wait!"); + try { + Thread.sleep(5000); + } catch (Exception e2) { + } + } + } while (dest == null); + + // check children of this entry + compareAndWaitEntries(conn1, conn2, source.getDN()); + } // while + } catch (Exception ex) { + CMS.debug("DatabasePanel comparetAndWaitEntries " + ex); + } + } + + /** + * 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 boolean isAgreementExist(String replicadn, LDAPConnection conn, + String name) { + String dn = "cn="+name+","+replicadn; + String filter = "(cn="+name+")"; + String[] attrs = {"cn"}; + try { + LDAPSearchResults results = conn.search(dn, LDAPv3.SCOPE_SUB, + filter, attrs, false); + while (results.hasMoreElements()) + return true; + } catch (LDAPException e) { + return false; + } + + return false; + } + + private void createReplicationManager(LDAPConnection conn, String pwd) + throws LDAPException { + LDAPAttributeSet attrs = null; + LDAPEntry entry = null; + String dn = "cn=Replication Manager,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", "Replication Manager")); + attrs.add(new LDAPAttribute("sn", "manager")); + entry = new LDAPEntry("cn=Replication Manager,cn=config", + 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 create 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("cn=changelog5,cn=config", 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 void enableReplication(String replicadn, LDAPConnection conn, String basedn, String 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=replication manager,cn=config")); + attrs.add(new LDAPAttribute("cn", "replica")); + attrs.add(new LDAPAttribute("nsDS5ReplicaId", 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) { + CMS.debug("DatabasePanel enableReplication: "+replicadn+" has already used"); + try { + conn.delete(replicadn); + conn.add(entry); + } catch (LDAPException ee) { + } + return; + } else { + CMS.debug("DatabasePanel enableReplication: Failed to create "+replicadn+" entry. Exception: "+e.toString()); + return; + } + } + + CMS.debug("DatabasePanel enableReplication: Successfully create "+replicadn+" entry."); + } + + private void createReplicationAgreement(String replicadn, + LDAPConnection conn, String name, String replicahost, int replicaport, + String replicapwd, String basedn) 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=replication manager,cn=config")); + attrs.add(new LDAPAttribute("nsDS5ReplicaBindMethod", "Simple")); + attrs.add(new LDAPAttribute("nsds5replicacredentials", replicapwd)); + 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 String getInstanceDir(LDAPConnection conn) { + String instancedir=""; + try { + String filter = "(objectclass=nsslapdConfig)"; + String[] attrs = {"nsslapd-instancedir"}; + LDAPSearchResults results = conn.search("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-instancedir: "+dn); + LDAPAttributeSet entryAttrs = entry.getAttributeSet(); + Enumeration attrsInSet = entryAttrs.getAttributes(); + while (attrsInSet.hasMoreElements()) { + LDAPAttribute nextAttr = (LDAPAttribute)attrsInSet.nextElement(); + String attrName = nextAttr.getName(); + CMS.debug("DatabasePanel getInstanceDir: attribute name: "+attrName); + Enumeration valsInAttr = nextAttr.getStringValues(); + while ( valsInAttr.hasMoreElements() ) { + String nextValue = (String)valsInAttr.nextElement(); + if (attrName.equalsIgnoreCase("nsslapd-instancedir")) { + CMS.debug("DatabasePanel getInstanceDir: instanceDir="+nextValue); + return nextValue; + } + } + } + } + } catch (LDAPException e) { + CMS.debug("DatabasePanel getInstanceDir: Error in retrieving the instance directory. Exception: "+e.toString()); + } + + return instancedir; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabaseServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabaseServlet.java new file mode 100644 index 000000000..03f8f2f86 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DatabaseServlet.java @@ -0,0 +1,45 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + + +public class DatabaseServlet extends BaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java new file mode 100644 index 000000000..a27bcf09d --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DisplayCertChainPanel.java @@ -0,0 +1,221 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import org.xml.sax.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cmsutil.xml.*; +import java.io.*; +import java.net.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import com.netscape.cmsutil.http.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.asn1.*; +import netscape.security.util.*; +import netscape.security.x509.X509CertImpl; + +import com.netscape.cmsutil.crypto.*; +import com.netscape.cms.servlet.wizard.*; + +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("preop.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 v = new Vector(); + + 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 hostname = cs.getString("preop.securitydomain.host", ""); + int port = cs.getInteger("preop.securitydomain.httpsport", -1); + String subsystem = cs.getString("cs.type", ""); + String urlVal = "https://"+CMS.getEESSLHost()+":"+CMS.getEESSLPort()+"/"+toLowerCaseSubsystemType(subsystem)+"/admin/console/config/wizard?p="+panel+"&subsystem="+subsystem; + String encodedValue = URLEncoder.encode(urlVal, "UTF-8"); + String sdurl = "https://"+hostname+":"+port+"/ca/ee/ca/securityDomainLogin?url="+encodedValue; + response.sendRedirect(sdurl); + } catch (Exception ee) { + CMS.debug("DisplayCertChainPanel Exception="+ee.toString()); + } + } + } + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/DisplayServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DisplayServlet.java new file mode 100644 index 000000000..2c0184f26 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DisplayServlet.java @@ -0,0 +1,45 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + + +public class DisplayServlet extends BaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java new file mode 100644 index 000000000..28008a451 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DonePanel.java @@ -0,0 +1,499 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.csadmin; + + +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cmsutil.util.Cert; +import netscape.security.x509.*; +import netscape.ldap.*; +import java.net.*; +import java.io.*; +import java.math.*; +import java.security.cert.*; +import org.w3c.dom.*; + +import com.netscape.cms.servlet.wizard.*; + +public class DonePanel extends WizardPanelBase { + + public static final BigInteger BIG_ZERO = new BigInteger("0"); + public static final Long MINUS_ONE = Long.valueOf(-1); + + 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; + } + + /** + * 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 ownsport = CMS.getEESSLPort(); + String ownhost = CMS.getEESSLHost(); + String select = ""; + + String type = ""; + String instanceId = ""; + try { + type = cs.getString("cs.type", ""); + instanceId = cs.getString("instanceId"); + select = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) {} + + context.put("instanceId", instanceId); + context.put("title", "Done"); + context.put("panel", "admin/console/config/donepanel.vm"); + context.put("host", ownhost); + context.put("port", ownsport); + 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_port = ""; + String sd_host = ""; + String ca_host = ""; + try { + sd_host = cs.getString("preop.securitydomain.host", ""); + sd_port = cs.getString("preop.securitydomain.httpsport", ""); + 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 instanceName = ""; + String subsystemName = ""; + try { + sdtype = cs.getString("preop.securitydomain.select", ""); + instanceName = cs.getString("instanceId", ""); + subsystemName = cs.getString("preop.subsystem.name", ""); + } catch (Exception e) { + } + + String s = getSubsystemNodeName(type); + if (sdtype.equals("new")) { + try { + String instanceRoot = cs.getString("instanceRoot", ""); + String domainxml = instanceRoot+"/conf/domain.xml"; + XMLObject obj = new XMLObject(new FileInputStream(domainxml)); + Node n = obj.getContainer(s); + NodeList nlist = n.getChildNodes(); + String countS = ""; + 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; + } + } + Node parent = obj.createContainer(n, type); + obj.addItemToContainer(parent, "SubsystemName", subsystemName); + obj.addItemToContainer(parent, "Host", sd_host); + obj.addItemToContainer(parent, "SecurePort", sd_port); + obj.addItemToContainer(parent, "DomainManager", "true"); + obj.addItemToContainer(parent, "Clone", "false"); + + CMS.debug("DonePanel display: SubsystemCount="+countS); + int count = 0; + try { + count = Integer.parseInt(countS); + count++; + } catch (Exception ee) { + } + + Node nn2 = n.removeChild(countnode); + obj.addItemToContainer(n, "SubsystemCount", ""+count); + CMS.debug("DonePanel display: finish updating domain.xml"); + byte[] b = obj.toByteArray(); + FileOutputStream fos = new FileOutputStream(domainxml); + fos.write(b); + fos.close(); + } catch (Exception e) { + CMS.debug("DonePanel display: "+e.toString()); + } + } else { //existing domain + int p = -1; + try { + p = Integer.parseInt(sd_port); + } catch (Exception e) { + } + + try { + String cloneStr = ""; + if (select.equals("clone")) + cloneStr = "&clone=true"; + else + cloneStr = "&clone=false"; + updateDomainXML(sd_host, p, true, "/ca/agent/ca/updateDomainXML", + "list="+s+"&type="+type+"&host="+ownhost+"&name="+subsystemName+"&sport="+ownsport+"&dm=false"+cloneStr); + } catch (Exception e) { + context.put("errorString", "Failed to update the domain.xml."); + return; + } + } + + // need to push connector information to the CA + if (type.equals("KRA") && !ca_host.equals("")) { + try { + updateConnectorInfo(ownhost, ownsport, sd_host, sd_port); + } catch (IOException e) { + context.put("errorString", "Failed to update connector information."); + return; + } + + // 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) { + } + } // 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."); + } + } + + if (!select.equals("clone")) { + if (type.equals("CA") || type.equals("KRA")) { + String beginRequestNumStr = ""; + String endRequestNumStr = ""; + String beginSerialNumStr = ""; + String endSerialNumStr = ""; + String requestIncStr = ""; + String serialIncStr = ""; + + 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"); + cs.putString("dbs.nextBeginRequestNumber", + endRequestNum.add(oneNum).toString()); + cs.putString("dbs.nextBeginSerialNumber", + endSerialNum.add(oneNum).toString()); + } catch (Exception e) { + } + } + } + + cs.putInteger("cs.state", 1); + cs.removeSubStore("preop"); + try { + cs.commit(false); + } catch (Exception e) { + } + + context.put("csstate", "1"); + } + + private void updateOCSPConfig(HttpServletResponse response) + throws IOException { + IConfigStore config = CMS.getConfigStore(); + String cahost = ""; + int caport = -1; + String sdhost = ""; + int sdport = -1; + + try { + cahost = config.getString("preop.ca.hostname", ""); + caport = config.getInteger("preop.ca.httpsport", -1); + sdhost = config.getString("preop.securitydomain.host", ""); + sdport = config.getInteger("preop.securitydomain.httpsport", -1); + } catch (Exception e) { + } + + String ocsphost = CMS.getEESSLHost(); + int ocspport = Integer.parseInt(CMS.getEESSLPort()); + 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.httpsport", -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 ownhost, String ownsport, + String sd_host, String sd_port) + throws IOException { + IConfigStore cs = CMS.getConfigStore(); + int port = -1; + URL urlx = null; + String url = ""; + String host = null; + String transportCert = ""; + try { + url = cs.getString("preop.ca.url", ""); + if (!url.equals("")) { + urlx = new URL(url); + host = urlx.getHost(); + port = urlx.getPort(); + 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="+ownhost+"&ca.connector.KRA.port="+ownsport+"&ca.connector.KRA.transportCert="+URLEncoder.encode(transportCert)+"&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/pki/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.java new file mode 100644 index 000000000..ecc1e7e40 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/DownloadPKCS12.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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import com.netscape.certsrv.connector.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cmsutil.crypto.*; + +public class DownloadPKCS12 extends CMSServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetCertChain.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetCertChain.java new file mode 100644 index 000000000..3a9a36e91 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetCertChain.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.csadmin; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; + + +public class GetCertChain extends CMSServlet { + + 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 { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + String outputString = null; + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.java new file mode 100644 index 000000000..6b1fd1e99 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetConfigEntries.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.*; +import java.util.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.password.*; +import org.w3c.dom.*; + +public class GetConfigEntries extends CMSServlet { + + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + 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 { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + 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 enum1 = cs.getPropertyNames(); + + while (enum1.hasMoreElements()) { + String name = name1+"."+enum1.nextElement(); + try { + String value = config.getString(name); + 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", ""); + } catch (Exception ee) { + if (name.equals("internaldb.ldapauth.password")) { + value = getLDAPPassword(); + } 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"); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetCookie.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetCookie.java new file mode 100644 index 000000000..ce9142ca7 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetCookie.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.csadmin; + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import java.net.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; + + +public class GetCookie extends CMSServlet { + + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private static Random mRandom = null; + private final static int SESSION_MAX_AGE = 3600; + private String mErrorFormPath = null; + private String mFormPath = null; + + 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; + int sessionMaxAge = SESSION_MAX_AGE; + IConfigStore cs = CMS.getConfigStore(); + try { + sessionMaxAge = cs.getInteger("sessionMaxAge", SESSION_MAX_AGE); + } catch (Exception e) { + } + + 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("preop.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 = ""; + if (authToken != null) { + String uid = authToken.getInString("uid"); + String groupname = getGroupName(uid, subsystem); + + if (groupname != null) { + // 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) { + } + + ctable.addEntry(cookie, ip, uid, groupname); + try { + String sd_url = "https://"+CMS.getEESSLHost()+":"+CMS.getEESSLPort(); + 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); + + EBaseException error = null; + try { + ServletOutputStream out = httpResp.getOutputStream(); + + if (error == null) { + cmsReq.setStatus(CMSRequest.SUCCESS); + httpResp.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")); + } + } + } catch (Exception e) { + } + } + } + } + + private String getGroupName(String uid, String subsystemname) { + String groupname = ""; + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetDomainXML.java new file mode 100644 index 000000000..09fb91c6a --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetDomainXML.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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + + +public class GetDomainXML extends CMSServlet { + + 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..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + String outputString = null; + + String path = CMS.getConfigStore().getString("instanceRoot", "") + + "/conf/domain.xml"; + + CMS.debug("GetDomainXML: got path=" + path); + + try { + CMS.debug("GetDomainXML: Reading domain.xml..."); + 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..."); + + XMLObject xmlObj = new XMLObject(); + Node root = xmlObj.createRoot("XMLResponse"); + + xmlObj.addItemToContainer(root, "Status", SUCCESS); + xmlObj.addItemToContainer(root, "DomainInfo", new String(buf)); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("GetDomainXML: 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetStatus.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetStatus.java new file mode 100644 index 000000000..5f533fbe4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetStatus.java @@ -0,0 +1,115 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; + + +public class GetStatus extends CMSServlet { + + 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 { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + IConfigStore config = CMS.getConfigStore(); + + String outputString = null; + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.java new file mode 100644 index 000000000..ab6a1aa01 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetSubsystemCert.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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.csadmin; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.crypto.*; +import org.w3c.dom.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.X509Certificate; + + +public class GetSubsystemCert extends CMSServlet { + + 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 { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + String outputString = null; + + 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; + } + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java new file mode 100644 index 000000000..47b8bd3f9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetTokenInfo.java @@ -0,0 +1,147 @@ +// --- 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.*; +import java.util.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.password.*; +import org.w3c.dom.*; + +public class GetTokenInfo extends CMSServlet { + + 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 { + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + 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("preop.cert.list"); + } catch (Exception e) { + } + + StringTokenizer t1 = new StringTokenizer(certlist, ","); + while (t1.hasMoreTokens()) { + String name = t1.nextToken(); + if (name.equals("sslserver")) + continue; + name = "preop.cert."+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 = "preop.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/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java new file mode 100644 index 000000000..841d777fd --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/GetTransportCert.java @@ -0,0 +1,189 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.util.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import com.netscape.certsrv.connector.*; +import com.netscape.certsrv.ca.*; + +/** + * This servlet retrieves the transport certificate from DRM. + */ +public class GetTransportCert extends CMSServlet { + + 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..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + 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, + "modify"); + 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; + } + + IConfigStore cs = CMS.getConfigStore(); + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/HierarchyPanel.java new file mode 100644 index 000000000..37231edfa --- /dev/null +++ b/pki/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 org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.dbs.certdb.*; +import java.io.*; +import java.net.URL; +import com.netscape.cmsutil.crypto.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.base.*; + +import java.util.*; +import java.security.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.KeyPairGenerator; + +import netscape.security.x509.*; +import com.netscape.cms.servlet.wizard.*; + +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"); + return true; + } + } catch (EBaseException e) { + } + + return false; + } + + public void cleanUp() throws IOException { + IConfigStore cs = CMS.getConfigStore(); + cs.putString("preop.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")) + return; + } catch (Exception e) { + } + + String select = HttpInput.getID(request, "choice"); + + if (select == null) { + CMS.debug("HierarchyPanel: choice not found"); + throw new IOException("choice not found"); + } + + if (select.equals("root")) { + config.putString("preop.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"); + } else { + config.putString(PCERT_PREFIX + "signing.type", "remote"); + CMS.debug("HierarchyPanel: invalid choice " + select); + throw new IOException("invalid choice " + select); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) {} +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.java new file mode 100644 index 000000000..732adf8f5 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ImportAdminCertPanel.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 org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.cmsutil.crypto.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import java.io.*; +import java.math.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.util.*; +import netscape.security.pkcs.*; +import netscape.security.x509.*; + +import org.mozilla.jss.asn1.*; +import com.netscape.cms.servlet.wizard.*; + +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 s = ""; + try { + s = cs.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + String type = ""; + String subsystemtype = ""; + + try { + type = cs.getString("preop.ca.type", ""); + subsystemtype = cs.getString("cs.type", ""); + } catch (Exception e) {} + + if (s.equals("clone")) { + context.put("import", "false"); + return; + } + + 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 { + caHost = cs.getString("preop.securitydomain.host", ""); + caPort = cs.getString("preop.securitydomain.httpsport", ""); + } catch (Exception e) {} + } else if (type.equals("sdca")) { + try { + caHost = cs.getString("preop.ca.hostname", ""); + caPort = cs.getString("preop.ca.httpsport", ""); + } 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 select = ""; + try { + select = cs.getString("preop.subsystem.select", ""); + context.put("select", select); + } catch (Exception e) { + } + + String type = ""; + String subsystemtype = ""; + + try { + type = cs.getString("preop.ca.type", ""); + subsystemtype = cs.getString("cs.type", ""); + } catch (Exception e) {} + + if (select.equals("clone")) + return; + + 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]; + + if (ca != null) { + String serialno = null; + + try { + serialno = cs.getString("preop.admincert.serialno.0"); + } catch (Exception e) { + CMS.debug( + "ImportAdminCertPanel update: Failed to get request id."); + 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; + + 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) { + throw new IOException(e.toString()); + } + } catch (Exception e) { + CMS.debug( + "ImportAdminCertPanel update: failed to add certificate. Exception: " + + e.toString()); + 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"); + } + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java new file mode 100644 index 000000000..1d884856f --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ImportTransportCert.java @@ -0,0 +1,195 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import com.netscape.certsrv.connector.*; +import com.netscape.certsrv.ca.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.PrivateKey.Type; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.util.*; +import org.mozilla.jss.pkcs12.*; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.pkix.primitive.Attribute; +import java.security.interfaces.*; + +/** + * This servlet imports DRM's transport certificate into TKS. + */ +public class ImportTransportCert extends CMSServlet { + + 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 name = httpReq.getParameter("name"); + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/LoginServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/LoginServlet.java new file mode 100644 index 000000000..ca3879adb --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/LoginServlet.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.csadmin; + + +import java.util.*; + +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.CMS; + + +public class LoginServlet extends BaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/MainPageServlet.java new file mode 100644 index 000000000..2ebaf75af --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/MainPageServlet.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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.csadmin; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.ILogger; + +public class MainPageServlet extends CMSServlet { + 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); + + EBaseException error = null; + try { + ServletOutputStream out = response.getOutputStream(); + + if (error == null) { + cmsReq.setStatus(CMSRequest.SUCCESS); + response.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")); + } + } + + 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.getEESSLPort()).intValue()); + rarg.addStringValue("host", host); + rarg.addStringValue("uri", agentInterface); + argSet.addRepeatRecord(rarg); + num++; + } + } + header.addIntegerValue("totalRecordCount", num); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/ModulePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ModulePanel.java new file mode 100644 index 000000000..be20a849b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ModulePanel.java @@ -0,0 +1,328 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.property.*; +import java.io.*; +import com.netscape.certsrv.apps.CMS; + +import com.netscape.cmsutil.crypto.*; +import java.util.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkcs11.*; + +import com.netscape.cms.servlet.wizard.*; + +public class ModulePanel extends WizardPanelBase { + private CryptoManager mCryptoManager = null; + private Vector mSupportedModules = null; + private Vector mOtherModules = null; + private Hashtable mCurrModTable = new Hashtable(); + 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(); + Enumeration modules = mCryptoManager.getModules(); + + while (modules.hasMoreElements()) { + PK11Module mod = (PK11Module) 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 m = mCurrModTable.elements(); + + mOtherModules = new Vector(); + while (m.hasMoreElements()) { + PK11Module mod = (PK11Module) m.nextElement(); + Enumeration s = mSupportedModules.elements(); + boolean found = false; + + while (s.hasMoreElements()) { + Module sm = (Module) 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((Object) module); + break; + } + }// while + } + + /* + * find all tokens belonging to a module and load the Module + */ + public void loadModTokens(Module module, PK11Module mod) { + Enumeration tokens = mod.getTokens(); + + while (tokens.hasMoreElements()) { + try { + CryptoToken token = (CryptoToken) 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(); + // 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 = (PK11Module) mCurrModTable.get(cn); + + loadModTokens(module, m); + } + + CMS.debug("ModulePanel: adding module " + cn); + // add module to set + if (!mSupportedModules.contains(module)) { + mSupportedModules.addElement((Object) 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); + } catch (Exception e) { + CMS.debug("ModulePanel: Exception caught: " + e.toString()); + System.err.println("Exception caught: " + e.toString()); + } + } + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/ModuleServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ModuleServlet.java new file mode 100644 index 000000000..9230ef5b7 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/ModuleServlet.java @@ -0,0 +1,86 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.CMS; + + +public class ModuleServlet extends BaseServlet { + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/NamePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/NamePanel.java new file mode 100644 index 000000000..8eafdeac5 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/NamePanel.java @@ -0,0 +1,838 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import java.util.*; +import java.io.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.certdb.*; + +import com.netscape.cmsutil.crypto.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.base.*; +import java.net.*; +import java.security.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.KeyPairGenerator; + +import netscape.security.x509.*; + +import com.netscape.cms.servlet.wizard.*; + +public class NamePanel extends WizardPanelBase { + private Vector 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 { + boolean done = cs.getBoolean("preop.NamePanel.done"); + 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(); + + 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("preop.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("preop.securitydomain.select"); + int count = 0; + String host = ""; + int sport = -1; + if (domaintype.equals("existing")) { + host = config.getString("preop.securitydomain.host", ""); + sport = config.getInteger("preop.securitydomain.httpsport", -1); + count = getSubsystemCount(host, sport, 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("preop.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 { + boolean done = config.getBoolean("preop.NamePanel.done"); + c.setDN(dn); + } catch (Exception e) { + 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+ ((o_sd)? (",O=" + domainname):"")); + config.putBoolean(PCERT_PREFIX+certTag+".updatedDN", true); + } else { + c.setDN(dn + ((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 urls"); + Vector v = getUrlListFromSecurityDomain(config, "CA"); + 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 c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert 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) { + throw new IOException("Empty DN for " + cert.getUserFriendlyName()); + } + } + } // while + } + + /* + * 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; + } + File file = new File(path+"/conf/serverCertNick.conf"); + 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); + /* + config.putString(CERT_PREFIX + certTag + ".defaultSigningAlgorithm", + "SHA1withRSA"); + */ + + 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_port = -1; + try { + sd_hostname = config.getString("preop.securitydomain.host", ""); + sd_port = config.getInteger("preop.securitydomain.httpsport", -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_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 c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = (Cert) c.nextElement(); + String ct = cert.getCertTag(); + CMS.debug("NamePanel: configCertWithTag ct=" + ct + + " tag=" +tag); + if (ct.equals(tag)) { + 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 c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert 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; + } + } 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()) { + 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 is required for setting KRA connector + url = url.substring(url.indexOf("https")); + config.putString("preop.ca.url", url); + } + CMS.debug("NamePanel: clone configuration done"); + return; + } + } catch (Exception e) { + CMS.debug("NamePanel: configCertWithTag failure - " + e); + return; + } + + //if no hselect, then not CA + if (hselect.equals("") || hselect.equals("join")) { + String select = null; + String url = getURL(request, config); + + URL urlx = null; + + if (url.equals("External CA")) { + CMS.debug("NamePanel: external CA selected"); + select = "otherca"; + 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"); + select = "sdca"; + // parse URL (CA1 - http://...) + 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 c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = (Cert) c.nextElement(); + String ct = cert.getCertTag(); + String nickname = cert.getNickname(); + String tokenname = cert.getTokenname(); + 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 dn's and put in config + String dn = HttpInput.getDN(request, cert.getCertTag()); + + config.putString(PCERT_PREFIX + cert.getCertTag() + ".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) {} + + + CMS.debug("NamePanel: update() done"); + } + + private void sdca(HttpServletRequest request, Context context, String hostname, String httpPortStr) throws IOException { + CMS.debug("NamePanel update: this is the CA in the security domain."); + CMS.debug("NamePanel update: selected CA hostname=" + hostname + " port=" + httpPortStr); + IConfigStore config = CMS.getConfigStore(); + + context.put("sdcaHostname", hostname); + context.put("sdHttpPort", httpPortStr); + + if (hostname == null || hostname.length() == 0) { + context.put("errorString", "Hostname is null"); + throw new IOException("Hostname is null"); + } + + int httpport = -1; + + try { + httpport = Integer.parseInt(httpPortStr); + } catch (Exception e) { + CMS.debug( + "NamePanel update: Http 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", httpPortStr); + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + updateCertChain(config, "ca", hostname, httpport, 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java new file mode 100644 index 000000000..2bc5f94fc --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/RegisterUser.java @@ -0,0 +1,255 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import com.netscape.certsrv.connector.*; +import com.netscape.certsrv.ca.*; + +/** + * 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 final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + private String mGroupName = null; + + 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; + } + + IConfigStore cs = CMS.getConfigStore(); + + // 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); + + 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 = (byte[]) (com.netscape.osutil.OSUtil.AtoB(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); + } + + user.setX509Certificates(certs); + if (!foundByCert) { + ugsys.addUserCert(user); + CMS.debug("RegisterUser added user certificate"); + } else + CMS.debug("RegisterUser no need to add user certificate"); + } catch (Exception eee) { + CMS.debug("RegisterUser error " + eee.toString()); + outputError(httpResp, "Error: Certificate malformed"); + return; + } + + + // add user to the group + Enumeration groups = ugsys.findGroups(mGroupName); + IGroup group = (IGroup)groups.nextElement(); + group.addMemberName(user.getUserID()); + ugsys.modifyGroup(group); + CMS.debug("RegisterUser modified group"); + + // 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java new file mode 100644 index 000000000..bf0be9b6e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/RestoreKeyCertPanel.java @@ -0,0 +1,675 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import java.security.*; +import java.math.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import java.io.*; +import java.net.URL; +import com.netscape.certsrv.base.*; +import java.util.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.util.*; +import org.mozilla.jss.pkcs12.*; +import org.mozilla.jss.pkcs11.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.crypto.PrivateKey.Type; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.pkix.primitive.Attribute; +import com.netscape.cms.servlet.wizard.*; +import netscape.ldap.*; +import java.security.interfaces.*; + +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 { + boolean done = cs.getBoolean("preop.restorekeycert.done"); + 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", ""); + String type = config.getString("preop.subsystem.select", ""); + 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"); + 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); + return; + } + String pwd = HttpInput.getPassword(request, "password"); + + String tokenn = ""; + try { + tokenn = config.getString("preop.module.token"); + } catch (Exception e) { + } + + if (tokenn.equals("Internal Key Storage Token")) { + byte b[] = new byte[1000000]; + FileInputStream fis = new FileInputStream(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 pkeyinfo_collection = new Vector(); + Vector cert_collection = new Vector(); + 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(); + PasswordConverter passConverter = new PasswordConverter(); + PrivateKeyInfo pkeyinfo = privkeyinfo.decrypt(password, new PasswordConverter()); + Vector pkeyinfo_v = new Vector(); + 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 cert_v = new Vector(); + 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 { + 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"); + throw new IOException("Clone is not ready"); + } + } + + config.putBoolean("preop.restorekeycert.done", true); + try { + config.commit(false); + } catch (EBaseException e) { + } + + getConfigEntriesFromMaster(request, response, context); + } + + 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 sd_hostname = ""; + int sd_port = -1; + String master_hostname = ""; + int master_port = -1; + try { + sd_hostname = config.getString("preop.securitydomain.host", ""); + sd_port = config.getInteger("preop.securitydomain.httpsport", -1); + master_hostname = config.getString("preop.master.hostname", ""); + master_port = config.getInteger("preop.master.httpsport", -1); + + String content = ""; + if (cstype.equals("ca") || cstype.equals("kra")) { + String increment = config.getString("dbs.requestNumber.increment", ""); + String previncrement = config.getString("dbs.requestNumber.previncrement", ""); + if (!increment.equals(previncrement)) { + content = "type=request&xmlOutput=true&sessionID="+session_id+"&increment="+increment; + CMS.debug("http content=" + content); + updateNumberRange(master_hostname, master_port, true, content, "request", response); + config.putString("dbs.requestNumber.previncrement", increment); + config.commit(false); + } + + previncrement = config.getString("dbs.serialNumber.previncrement", ""); + increment = config.getString("dbs.serialNumber.increment", ""); + if (!increment.equals(previncrement)) { + content = "type=serialNo&xmlOutput=true&sessionID="+session_id+"&increment="+increment; + updateNumberRange(master_hostname, master_port, true, content, "serialNo", response); + config.putString("dbs.serialNumber.previncrement", increment); + config.commit(false); + } + } + + 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("preop.cert."); + c1.append(t1); + c1.append(".nickname,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".dn,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".keytype,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".privkey.id,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".pubkey.exponent,"); + c1.append("preop.cert."); + c1.append(t1); + c1.append(".pubkey.modulus"); + + 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"); + } + + content = "op=get&names=preop.module.token,instanceId,internaldb.basedn,internaldb.ldapauth.password,internaldb.ldapconn.host,internaldb.ldapconn.port,internaldb.ldapauth.bindDN"+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 pkeyinfo_collection, + Vector 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 pkeyinfo_v = (Vector)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); + org.mozilla.jss.crypto.PrivateKey pp = 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 cert_v = (Vector)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 + 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 cert_collection) + throws IOException { + for (int i=0; i<cert_collection.size(); i++) { + Vector v = (Vector)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", ""); + CryptoToken tok = cm.getTokenByName(tokenname); + CryptoStore store = tok.getCryptoStore(); + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.java new file mode 100644 index 000000000..84ddd2e7c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SavePKCS12Panel.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 org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import org.mozilla.jss.util.Password; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import java.io.*; +import java.net.URL; +import com.netscape.certsrv.base.*; +import java.util.*; +import java.security.*; +import java.security.cert.*; +import java.security.KeyPair; +import netscape.security.util.*; +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import org.mozilla.jss.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkcs12.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.crypto.X509Certificate; +import org.mozilla.jss.crypto.PrivateKey; + +import com.netscape.cms.servlet.wizard.*; + +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"); + } + + /** + * 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.java new file mode 100644 index 000000000..41bac6413 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainLogin.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.csadmin; + + +import java.util.*; +import java.net.*; +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; + +public class SecurityDomainLogin extends BaseServlet { + + 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); + IConfigStore cs = CMS.getConfigStore(); + String sdname = cs.getString("preop.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/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java new file mode 100644 index 000000000..e5bf90343 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainPanel.java @@ -0,0 +1,419 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; +import org.mozilla.jss.crypto.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.base.*; +import com.netscape.cmsutil.crypto.*; +import java.net.*; +import java.io.*; +import java.util.*; +import java.security.cert.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; + +import com.netscape.cms.servlet.wizard.*; + +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 url = ""; + String name = ""; + + try { + url = config.getString("preop.securitydomain.url", ""); + name = config.getString("preop.securitydomain.name", ""); + } 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("https_port", CMS.getEESSLPort()); + context.put("http_port", CMS.getEENonSSLPort()); + } catch (EBaseException e) {} + + context.put("panel", "admin/console/config/securitydomainpanel.vm"); + context.put("errorString", errorString); + + if (url != null) { + String r = null; + + try { + URL u = new URL(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) { + CMS.debug("SecurityDomainPanel: pingCS returns: "+r); + context.put("sdomainURL", url); + } else { + CMS.debug("SecurityDomainPanel: pingCS no successful response"); + context.put("sdomainURL", ""); + } + } + + // from url, find hostname, if fully qualified, get network + // domain name and generate default security domain name + if (name.equals("") && (url != null)) { + try { + URL u = new URL(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); + } + + 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); + throw new IOException("Missing name value for the security domain"); + } + } else if (select.equals("existingdomain")) { + String url = HttpInput.getURL(request, "sdomainURL"); + if (url == null || url.equals("")) { + initParams(request, context); + throw new IOException("Missing url value for the security domain"); + } + } + } + + 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 url = request.getParameter("sdomainURL"); + if (url == null) + url = ""; + context.put("sdomainURL", 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"); + 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.host", + CMS.getEENonSSLHost()); + config.putString("securitydomain.host", + CMS.getEENonSSLHost()); + config.putString("preop.securitydomain.httpport", + CMS.getEENonSSLPort()); + config.putString("preop.securitydomain.httpsport", + CMS.getEESSLPort()); + config.putString("securitydomain.httpsport", + CMS.getEESSLPort()); + config.putString("preop.securitydomain.name", + HttpInput.getDomainName(request, "sdomainName")); + + // 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) {} + + String instanceRoot = ""; + try { + instanceRoot = config.getString("instanceRoot", ""); + } catch (Exception e) { + } + + String domainxml = instanceRoot+"/conf/domain.xml"; + + // generate security domain file + try { + XMLObject xmlObj = new XMLObject(); + + CMS.debug("Building Domain Info..."); + Node root = xmlObj.createRoot("DomainInfo"); + + xmlObj.addItemToContainer(root, "Name", + HttpInput.getDomainName(request, "sdomainName")); + + // put our own info to the file (maybe we should do this later) + Node kraList = xmlObj.createContainer(root, "KRAList"); + Node tpsList = xmlObj.createContainer(root, "TPSList"); + Node ocspList = xmlObj.createContainer(root, "OCSPList"); + Node raList = xmlObj.createContainer(root, "RAList"); + Node tksList = xmlObj.createContainer(root, "TKSList"); + Node caList = xmlObj.createContainer(root, "CAList"); + xmlObj.addItemToContainer(caList, "SubsystemCount", "0"); + xmlObj.addItemToContainer(tksList, "SubsystemCount", "0"); + xmlObj.addItemToContainer(raList, "SubsystemCount", "0"); + xmlObj.addItemToContainer(ocspList, "SubsystemCount", "0"); + xmlObj.addItemToContainer(tpsList, "SubsystemCount", "0"); + xmlObj.addItemToContainer(kraList, "SubsystemCount", "0"); + + byte[] cb = xmlObj.toByteArray(); + FileOutputStream fos = new FileOutputStream(domainxml); + fos.write(cb); + fos.close(); + } catch (Exception e) { + CMS.debug("Failed to send the XML output"); + } + } 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 url = HttpInput.getURL(request, "sdomainURL"); + String hostname = ""; + int port = -1; + + if (url != null) { + try { + URL u = new URL(url); + + hostname = u.getHost(); + port = u.getPort(); + } catch (MalformedURLException e) { + errorString = "Malformed URL"; + throw new IOException(errorString); + } + + context.put("sdomainURL", url); + config.putString("preop.securitydomain.url", url); + config.putString("preop.securitydomain.host", hostname); + config.putString("securitydomain.host", hostname); + config.putInteger("preop.securitydomain.httpsport", port); + config.putInteger("securitydomain.httpsport", port); + } else { + config.putString("preop.securitydomain.url", ""); + } + + try { + config.commit(false); + } catch (EBaseException e) {} + + ConfigCertApprovalCallback certApprovalCallback = new ConfigCertApprovalCallback(); + updateCertChain(config, "securitydomain", hostname, port, true, + context, certApprovalCallback); + } else { + CMS.debug("SecurityDomainPanel: invalid choice " + select); + errorString = "Invalid choice"; + 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); + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + IConfigStore config = CMS.getConfigStore(); + try { + initParams(request, context); + } catch (IOException e) { + } + try { + context.put("machineName", config.getString("machineName")); + context.put("https_port", CMS.getEESSLPort()); + context.put("http_port", CMS.getEENonSSLPort()); + } catch (EBaseException e) {} + context.put("title", "Security Domain"); + context.put("panel", "admin/console/config/securitydomainpanel.vm"); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainSessionTable.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainSessionTable.java new file mode 100644 index 000000000..dabaee410 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainSessionTable.java @@ -0,0 +1,100 @@ +// --- 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.*; +import java.io.*; +import com.netscape.certsrv.base.*; + +/** + * This object stores the values for IP, uid and group based on the cookie id. + */ +public class SecurityDomainSessionTable + implements ISecurityDomainSessionTable { + + private Hashtable m_sessions; + private long m_timeToLive; + + public SecurityDomainSessionTable(long timeToLive) { + m_sessions = new Hashtable(); + m_timeToLive = timeToLive; + } + + public void addEntry(String sessionId, String ip, + String uid, String group) { + Vector v = new Vector(); + 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); + } + + public void removeEntry(String sessionId) { + m_sessions.remove(sessionId); + } + + public boolean isSessionIdExist(String sessionId) { + return m_sessions.containsKey(sessionId); + } + + public Enumeration getSessionIds() { + return m_sessions.keys(); + } + + public String getIP(String sessionId) { + Vector v = (Vector)m_sessions.get(sessionId); + if (v != null) + return (String)v.elementAt(0); + return null; + } + + public String getUID(String sessionId) { + Vector v = (Vector)m_sessions.get(sessionId); + if (v != null) + return (String)v.elementAt(1); + return null; + } + + public String getGroup(String sessionId) { + Vector v = (Vector)m_sessions.get(sessionId); + if (v != null) + return (String)v.elementAt(2); + return null; + } + + public long getBeginTime(String sessionId) { + Vector v = (Vector)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/pki/base/common/src/com/netscape/cms/servlet/csadmin/SessionTimer.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SessionTimer.java new file mode 100644 index 000000000..91564d15e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SessionTimer.java @@ -0,0 +1,47 @@ +// --- 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.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; + +public class SessionTimer extends TimerTask { + private ISecurityDomainSessionTable m_sessiontable = null; + + public SessionTimer(ISecurityDomainSessionTable table) { + super(); + m_sessiontable = table; + } + + public void run() { + Enumeration keys = m_sessiontable.getSessionIds(); + while (keys.hasMoreElements()) { + String sessionId = (String)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."); + } + } + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/SizePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SizePanel.java new file mode 100644 index 000000000..131eebd22 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/SizePanel.java @@ -0,0 +1,479 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import java.io.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.cmsutil.crypto.*; + +import java.security.interfaces.RSAPublicKey; +import java.util.*; +import java.security.*; +import org.mozilla.jss.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.crypto.KeyPairGenerator; + +import com.netscape.cms.servlet.wizard.*; + +public class SizePanel extends WizardPanelBase { + private Vector mCerts = null; + private WizardServlet mServlet = null; + + public static final String DEFAULT_ECC_KEY_SIZE = "256"; + public static final String DEFAULT_RSA_KEY_SIZE = "2048"; + 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 { + boolean done = cs.getBoolean("preop.SizePanel.done"); + 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()"); + context.put("title", "Key Pairs"); + context.put("firsttime", "false"); + String errorString = ""; + mCerts = new Vector(); + + IConfigStore config = CMS.getConfigStore(); + try { + boolean done = config.getBoolean("preop.SizePanel.done"); + } catch (Exception e) { + context.put("firsttime", "true"); + } + + String select = ""; + try { + select = config.getString("preop.subsystem.select", ""); + } catch (Exception e) { + } + + context.put("select", select); + try { + // same token for now + String token = config.getString(PRE_CONF_CA_TOKEN); + String certTags = config.getString("preop.cert.list"); + StringTokenizer st = new StringTokenizer(certTags, ","); + + 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); + 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("certs", mCerts); + context.put("errorString", errorString); + context.put("default_keysize", DEFAULT_RSA_KEY_SIZE); + 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"); + boolean done = false; + try { + done = config.getBoolean("preop.SizePanel.done"); + } 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 c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert 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 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", ""); + + 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.keysize.custom_size", + DEFAULT_ECC_KEY_SIZE); + config.putString("preop.keysize.size", DEFAULT_ECC_KEY_SIZE); + } 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 + ".keysize.select", + "default"); + if (keytype != null && keytype.equals("ecc")) { + config.putString(PCERT_PREFIX + ct + + ".keysize.custom_size", + DEFAULT_ECC_KEY_SIZE); + config.putString(PCERT_PREFIX + ct + ".keysize.size", + DEFAULT_ECC_KEY_SIZE); + } 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"); + 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 + ".keysize.select", + "custom"); + config.putString(PCERT_PREFIX + ct + ".keysize.custom_size", + HttpInput.getKeySize(request, ct + "_custom_size", keytype)); + config.putString(PCERT_PREFIX + ct + ".keysize.size", + HttpInput.getKeySize(request, ct + "_custom_size", keytype)); + } 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", ""); + if (!oldkeysize.equals(newkeysize) || + !oldkeytype.equals(newkeytype)) + 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()) { + return; + } + } catch (IOException e) { + CMS.debug("SizePanel: update() IOException caught: " + e.toString()); + throw e; + } catch (NumberFormatException e) { + CMS.debug("SizePanel: update() NumberFormatException caught: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("SizePanel: update() Exception caught: " + e.toString()); + } + + // generate key pair + Enumeration c = mCerts.elements(); + + while (c.hasMoreElements()) { + Cert cert = (Cert) c.nextElement(); + String ct = cert.getCertTag(); + boolean enable = true; + try { + enable = config.getBoolean(PCERT_PREFIX+ct+".enable", true); + } catch (Exception e) { + } + + if (!enable) + continue; + + try { + String keytype = config.getString(PCERT_PREFIX + ct + ".keytype"); + int keysize = config.getInteger( + PCERT_PREFIX + ct + ".keysize.size"); + + if (keytype.equals("rsa")) { + + createRSAKeyPair(token, keysize, config, ct); + } else { + createECCKeyPair(token, keysize, config, ct); + } + config.commit(false); + } catch (Exception e) { + CMS.debug(e); + CMS.debug("SizePanel: key generation failure: " + e.toString()); + throw new IOException("key generation failure"); + } + } // 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"); + + } + + public void createECCKeyPair(String token, int keysize, IConfigStore config, String ct) + throws NoSuchAlgorithmException, NoSuchTokenException, TokenException, CryptoManager.NotInitializedException + { + CMS.debug("Generating ECC key pair"); + KeyPair pair = null; + do { + pair = CryptoUtil.generateECCKeyPair(token, keysize); + // 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)); + + // set default signing algorithm for CA + String systemType = ""; + try { + systemType = config.getString("preop.system.name"); + } catch (Exception e1) { + } + + if (systemType.equals("OCSP")) { + if (ct.equals("signing")) { + config.putString("ocsp.signing.defaultSigningAlgorithm", + "SHA1withEC"); + } + } + + if (systemType.equals("CA")) { + if (ct.equals("signing")) { + config.putString("ca.signing.defaultSigningAlgorithm", + "SHA1withEC"); + config.putString("ca.crl.MasterCRL.signingAlgorithm", + "SHA1withEC"); + } + if (ct.equals("ocsp_signing")) { + config.putString("ca.ocsp_signing.defaultSigningAlgorithm", + "SHA1withEC"); + } + } + + } + + 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)); + + if (ct.equals("signing")) { + config.putString("ca.signing.defaultSigningAlgorithm", + "SHA1withRSA"); + config.putString("ca.crl.MasterCRL.signingAlgorithm", + "SHA1withRSA"); + } + if (ct.equals("ocsp_signing")) { + config.putString("ca.ocsp_signing.defaultSigningAlgorithm", + "SHA1withRSA"); + } + } + + /** + * If validiate() returns false, this method will be called. + */ + public void displayError(HttpServletRequest request, + HttpServletResponse response, + Context context) { + context.put("title", "Key Pairs"); + context.put("certs", mCerts); + context.put("default_keysize", DEFAULT_RSA_KEY_SIZE); + context.put("panel", "admin/console/config/sizepanel.vm"); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.java new file mode 100644 index 000000000..16376405f --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/TokenAuthenticate.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.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import javax.servlet.http.*; +import java.net.*; +import org.w3c.dom.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cms.servlet.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import com.netscape.cmsutil.xml.*; + +public class TokenAuthenticate extends CMSServlet { + + 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); + + 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"); + String hostname = table.getIP(sessionId); + if (hostname.equals(givenHost)) { + CMS.debug("TokenAuthentication: hostname and givenHost matched"); + uid = table.getUID(sessionId); + gid = table.getGroup(sessionId); + } else { + CMS.debug("TokenAuthentication: hostname=" + hostname + " and givenHost=" + givenHost + " is different"); + CMS.debug("TokenAuthenticate authenticate failed, wrong hostname."); + outputError(httpResp, "Error: Failed Authentication"); + return; + } + } 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateConnector.java new file mode 100644 index 000000000..d5c4f017d --- /dev/null +++ b/pki/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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import com.netscape.certsrv.connector.*; +import com.netscape.certsrv.ca.*; + + +public class UpdateConnector extends CMSServlet { + + 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(); + + Enumeration list = httpReq.getParameterNames(); + while (list.hasMoreElements()) { + String name = (String)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/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java new file mode 100644 index 000000000..2102e2fb7 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateDomainXML.java @@ -0,0 +1,217 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + + +public class UpdateDomainXML extends CMSServlet { + + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + 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..."); + } + + /** + * 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..."); + + HttpServletRequest httpReq = cmsReq.getHttpReq(); + HttpServletResponse httpResp = cmsReq.getHttpResp(); + + CMS.debug("UpdateDomainXML process: authentication starts"); + IAuthToken authToken = authenticate(cmsReq); + if (authToken == null) { + CMS.debug("UpdateDomainXML process: authToken is null"); + outputError(httpResp, "Error: not authenticated"); + } + 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, "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) { + CMS.debug("UpdateDomainXML process: authorization error"); + outputError(httpResp, "Error: Not authorized"); + return; + } + + String path = CMS.getConfigStore().getString("instanceRoot", "") + + "/conf/domain.xml"; + + CMS.debug("UpdateDomainXML: got path=" + path); + + try { + // set info into domain.xml + 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 domainmgr = httpReq.getParameter("dm"); + String clone = httpReq.getParameter("clone"); + + // insert info + CMS.debug("UpdateDomainXML: Inserting new domain info"); + XMLObject parser = new XMLObject(new FileInputStream(path)); + Node n = parser.getContainer(list); + Node parent = parser.createContainer(n, type); + parser.addItemToContainer(parent, "SubsystemName", name); + parser.addItemToContainer(parent, "Host", host); + parser.addItemToContainer(parent, "SecurePort", sport); + parser.addItemToContainer(parent, "DomainManager", domainmgr); + parser.addItemToContainer(parent, "Clone", clone); + + 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); + int count = 0; + try { + count = Integer.parseInt(countS); + count++; + } catch (Exception ee) { + } + + Node nn2 = 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(); + + // 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", SUCCESS); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + } catch (Exception e) { + CMS.debug("UpdateDomainXML: 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java new file mode 100644 index 000000000..9c2ed9123 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateNumberRange.java @@ -0,0 +1,218 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + + +public class UpdateNumberRange extends CMSServlet { + + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + private final static String AUTH_FAILURE = "2"; + + 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; + } + + try { + String type = httpReq.getParameter("type"); + String incrementStr = httpReq.getParameter("increment"); + BigInteger increment = new BigInteger(incrementStr); + IConfigStore cs = CMS.getConfigStore(); + + BigInteger beginNum = null; + BigInteger endNum = null; + BigInteger oneNum = new BigInteger("1"); + BigInteger nextNum = null; + if (type.equals("request")) { + String beginNumStr = cs.getString("dbs.nextBeginRequestNumber"); + beginNum = new BigInteger(beginNumStr); + if( beginNum == null ) { + CMS.debug( "UpdateNumberRange::process() - " + + "request beginNum is null!" ); + return; + } + endNum = beginNum.add(increment); + if( endNum == null ) { + CMS.debug( "UpdateNumberRange::process() - " + + "request endNum is null!" ); + return; + } + nextNum = endNum.add(oneNum); + cs.putString("dbs.nextBeginRequestNumber", nextNum.toString()); + } else if (type.equals("serialNo")) { + String beginNumStr = cs.getString("dbs.nextBeginSerialNumber"); + beginNum = new BigInteger(beginNumStr); + if( beginNum == null ) { + CMS.debug( "UpdateNumberRange::process() - " + + "serialNo beginNum is null!" ); + return; + } + endNum = beginNum.add(increment); + if( endNum == null ) { + CMS.debug( "UpdateNumberRange::process() - " + + "serialNo endNum is null!" ); + return; + } + nextNum = endNum.add(oneNum); + cs.putString("dbs.nextBeginSerialNumber", nextNum.toString()); + } + + if( beginNum == null ) { + CMS.debug( "UpdateNumberRange::process() - " + + "beginNum is null!" ); + return; + } + + if( endNum == null ) { + CMS.debug( "UpdateNumberRange::process() - " + + "endNum is null!" ); + return; + } + + // 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()); + xmlObj.addItemToContainer(root, "endNumber", endNum.toString()); + byte[] cb = xmlObj.toByteArray(); + + outputResult(httpResp, "application/xml", cb); + cs.commit(false); + } catch (Exception e) { + CMS.debug("UpdateNumberRange: Failed to update number range. Exception: "+e.toString()); + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.java new file mode 100644 index 000000000..f105ea95b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/UpdateOCSPConfig.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.csadmin; + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.xml.*; +import org.w3c.dom.*; +import org.apache.xerces.parsers.DOMParser; +import org.apache.xerces.dom.*; +import javax.xml.parsers.*; +import javax.xml.transform.*; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + + +public class UpdateOCSPConfig extends CMSServlet { + + 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; + } + + String ocsphost = httpReq.getParameter("ocsp_host"); + String ocspport = httpReq.getParameter("ocsp_port"); + try { + IConfigStore cs = CMS.getConfigStore(); + 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.path", + "/ocsp/ee/ocsp/addCRL"); + cs.putString("ca.publish.publisher.instance.OCSPPublisher.pluginName", "OCSPPublisher"); + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WelcomePanel.java new file mode 100644 index 000000000..cb3cf7543 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WelcomePanel.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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.csadmin; + + +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import java.io.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; + +import com.netscape.cms.servlet.wizard.*; + +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/pki/base/common/src/com/netscape/cms/servlet/csadmin/WelcomeServlet.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WelcomeServlet.java new file mode 100644 index 000000000..2871b9e41 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WelcomeServlet.java @@ -0,0 +1,45 @@ +// --- 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.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; + + +public class WelcomeServlet extends BaseServlet { + + 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/pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java new file mode 100644 index 000000000..09771b3ca --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/csadmin/WizardPanelBase.java @@ -0,0 +1,1234 @@ +// --- 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.apache.velocity.context.Context; +import javax.servlet.http.*; +import javax.servlet.*; +import java.io.*; +import java.util.*; +import java.net.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.base.*; +import com.netscape.cms.servlet.wizard.*; +import com.netscape.cms.servlet.base.*; +import org.mozilla.jss.*; +import org.mozilla.jss.ssl.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.util.Base64OutputStream; +import org.mozilla.jss.pkcs11.*; +import netscape.security.x509.*; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.http.*; +import org.w3c.dom.*; +import org.xml.sax.*; +import java.security.cert.*; +import java.security.*; +import netscape.ldap.*; + +import com.netscape.cmsutil.crypto.*; +import com.netscape.cms.servlet.wizard.*; + +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("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 port, boolean https, + String type) + throws IOException { + CMS.debug("WizardPanelBase getSubsystemCount start"); + String c = getDomainXML(hostname, 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 port, boolean https) + throws IOException { + CMS.debug("WizardPanelBase getDomainXML start"); + String c = getHttpResponse(hostname, port, https, "/ca/ee/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 getCertChain(String hostname, int port, boolean https, + ConfigCertApprovalCallback certApprovalCallback) + throws IOException { + CMS.debug("WizardPanelBase getCertChain start"); + String c = getHttpResponse(hostname, 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::getCertChain() - " + + "Exception="+e.toString() ); + throw new IOException( e.toString() ); + } + + String status = parser.getValue("Status"); + + CMS.debug("WizardPanelBase getCertChain: status=" + status); + + if (status.equals(SUCCESS)) { + String certchain = parser.getValue("ChainBase64"); + + certchain = CryptoUtil.normalizeCertStr(certchain); + CMS.debug( + "WizardPanelBase getCertChain: certchain=" + + certchain); + return certchain; + } else { + String error = parser.getValue("Error"); + + throw new IOException(error); + } + } catch (IOException e) { + CMS.debug("WizardPanelBase: getCertChain: " + e.toString()); + throw e; + } catch (Exception e) { + CMS.debug("WizardPanelBase: getCertChain: " + 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)) { + 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.ldapconn.host")) { + config.putString("preop.internaldb.master.hostname", v); + } else if (name.equals("internaldb.ldapconn.port")) { + config.putString("preop.internaldb.master.port", v); + } else if (name.equals("internaldb.ldapauth.bindDN")) { + config.putString("preop.internaldb.master.binddn", v); + } else if (name.equals("internaldb.basedn")) { + config.putString(name, v); + config.putString("preop.internaldb.master.basedn", v); + } else if (name.equals("internaldb.ldapauth.password")) { + config.putString("preop.internaldb.master.bindpwd", v); + } else if (name.equals("instanceId")) { + config.putString("preop.master.instanceId", v); + } else if (name.equals("preop.cert.signing.nickname")) { + config.putString("preop.master.signing.nickname", v); + config.putString(name, v); + } else if (name.equals("preop.cert.ocsp_signing.nickname")) { + config.putString("preop.master.ocsp_signing.nickname", v); + config.putString(name, v); + } else if (name.equals("preop.cert.subsystem.nickname")) { + config.putString("preop.master.subsystem.nickname", v); + config.putString(name, v); + } else if (name.equals("preop.cert.transport.nickname")) { + config.putString("preop.master.transport.nickname", v); + config.putString("kra.transportUnit.nickName", v); + config.putString(name, v); + } else if (name.equals("preop.cert.storage.nickname")) { + config.putString("preop.master.storage.nickname", v); + config.putString("kra.storageUnit.nickName", v); + config.putString(name, v); + } else { + config.putString(name, v); + } + } + + 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 { + String error = parser.getValue("Error"); + 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); + } + 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 Vector getMasterUrlListFromSecurityDomain(IConfigStore config, String type) { + Vector v = new Vector(); + + try { + String hostname = config.getString("preop.securitydomain.host"); + int httpsport = config.getInteger("preop.securitydomain.httpsport"); + + CMS.debug("Getting domain.xml from CA..."); + String c = getDomainXML(hostname, httpsport, true); + String list = ""; + + CMS.debug("Type " + type); + if (type.equals("CA")) { + list = "CAList"; + } else if (type.equals("KRA")) { + list = "KRAList"; + } else if (type.equals("OCSP")) { + list = "OCSPList"; + } else if (type.equals("TKS")) { + list = "TKSList"; + } + + 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("preop.securitydomain.name", + parser.getValue("Name")); + + int len = nodeList.getLength(); + + CMS.debug("Len " + len); + for (int i = 0; i < len; i++) { + Vector v_clone = parser.getValuesFromContainer(nodeList.item(i), + "Clone"); + String clone = (String)v_clone.elementAt(0); + if (clone.equals("true")) + continue; + Vector v_name = parser.getValuesFromContainer(nodeList.item(i), + "SubsystemName"); + Vector v_host = parser.getValuesFromContainer(nodeList.item(i), + "Host"); + Vector v_port = parser.getValuesFromContainer(nodeList.item(i), + "SecurePort"); + + 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 getUrlListFromSecurityDomain(IConfigStore config, String type) { + Vector v = new Vector(); + + try { + String hostname = config.getString("preop.securitydomain.host"); + int httpsport = config.getInteger("preop.securitydomain.httpsport"); + + CMS.debug("Getting domain.xml from CA..."); + String c = getDomainXML(hostname, httpsport, true); + String list = ""; + + CMS.debug("Type " + type); + if (type.equals("CA")) { + list = "CAList"; + } else if (type.equals("KRA")) { + list = "KRAList"; + } else if (type.equals("OCSP")) { + list = "OCSPList"; + } else if (type.equals("TKS")) { + list = "TKSList"; + } + + 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("preop.securitydomain.name", + parser.getValue("Name")); + + int len = nodeList.getLength(); + + CMS.debug("Len " + len); + for (int i = 0; i < len; i++) { + Vector v_name = parser.getValuesFromContainer(nodeList.item(i), + "SubsystemName"); + Vector v_host = parser.getValuesFromContainer(nodeList.item(i), + "Host"); + Vector v_port = parser.getValuesFromContainer(nodeList.item(i), + "SecurePort"); + + 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 String pingCS(String hostname, int port, boolean https, + SSLCertificateApprovalCallback certApprovalCallback) + throws IOException { + CMS.debug("WizardPanelBase pingCS start"); + String c = getHttpResponse(hostname, port, https, "/ca/ee/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()); + } + } + + 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 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, 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("preop.cert.signing.nickname")) { config.putString("preop.master.signing.nickname", v); + config.putString(name, v); + } else if (name.equals("preop.cert.ocsp_signing.nickname")) { + config.putString("preop.master.ocsp_signing.nickname", v); + config.putString(name, v); + } else if (name.equals("preop.cert.subsystem.nickname")) { + config.putString("preop.master.subsystem.nickname", v); + config.putString(name, v); + } else if (name.equals("preop.cert.transport.nickname")) { + config.putString("preop.master.transport.nickname", v); + config.putString("kra.transportUnit.nickName", v); + config.putString(name, v); + } else if (name.equals("preop.cert.storage.nickname")) { + config.putString("preop.master.storage.nickname", v); + config.putString("kra.storageUnit.nickName", v); + config.putString(name, v); + } else { + config.putString(name, v); + } + } + } 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 port, boolean https, Context context) throws IOException { + updateCertChain(config, name, host, port, https, context, null); + } + + public void updateCertChain(IConfigStore config, String name, String host, + int port, boolean https, Context context, + ConfigCertApprovalCallback certApprovalCallback) throws IOException { + String certchain = getCertChain(host, 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("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); + } + } 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("preop.securitydomain.host", ""); + int port = cs.getInteger("preop.securitydomain.httpsport", -1); + int panel = getPanelNo(); + String subsystem = cs.getString("cs.type", ""); + String urlVal = "https://"+CMS.getEESSLHost()+":"+CMS.getEESSLPort()+"/"+toLowerCaseSubsystemType(subsystem)+"/admin/console/config/wizard?p="+panel+"&subsystem="+subsystem; + String encodedValue = URLEncoder.encode(urlVal, "UTF-8"); + String sdurl = "https://"+hostname+":"+port+"/ca/ee/ca/securityDomainLogin?url="+encodedValue; + response.sendRedirect(sdurl); + } catch (Exception e) { + CMS.debug("WizardPanelBase reloginSecurityDomain: Exception="+e.toString()); + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java b/pki/base/common/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java new file mode 100644 index 000000000..8dadd630b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/ConfirmRecoverBySerial.java @@ -0,0 +1,189 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.dbs.keydb.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ConfirmRecoverBySerial extends CMSServlet { + + 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(); + + IAuthToken authToken = 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); + + int seqNum = -1; + + try { + if (req.getParameter(IN_SERIALNO) != null) { + seqNum = Integer.parseInt( + 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, int seq, + HttpServletRequest req, HttpServletResponse resp, + Locale locale) { + try { + header.addIntegerValue(OUT_SERIALNO, seq); + 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(new BigInteger( + Integer.toString(seq))); + + KeyRecordParser.fillRecordIntoArg(rec, header); + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/key/DisplayBySerial.java b/pki/base/common/src/com/netscape/cms/servlet/key/DisplayBySerial.java new file mode 100644 index 000000000..708630bb4 --- /dev/null +++ b/pki/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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Display a specific Key Archival Request + * <P> + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisplayBySerial extends CMSServlet { + + 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); + int seqNum = -1; + + try { + if (req.getParameter(IN_SERIALNO) != null) { + seqNum = Integer.parseInt( + 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, int 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(new + BigInteger(Integer.toString(seq))); + + KeyRecordParser.fillRecordIntoArg(rec, header); + } catch (EBaseException e) { + header.addStringValue(OUT_ERROR, e.toString(locale)); + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java b/pki/base/common/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java new file mode 100644 index 000000000..a0850d0b4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/DisplayBySerialForRecovery.java @@ -0,0 +1,212 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Display a Specific Key Archival Request, and initiate + * key recovery process + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisplayBySerialForRecovery extends CMSServlet { + + 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); + + int seqNum = -1; + + try { + if (req.getParameter(IN_SERIALNO) != null) { + seqNum = Integer.parseInt( + 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, int 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(new + BigInteger(Integer.toString(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/pki/base/common/src/com/netscape/cms/servlet/key/DisplayTransport.java b/pki/base/common/src/com/netscape/cms/servlet/key/DisplayTransport.java new file mode 100644 index 000000000..b87231f32 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/DisplayTransport.java @@ -0,0 +1,135 @@ +// --- 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 com.netscape.cms.servlet.base.*; +import com.netscape.cms.servlet.common.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Retrieve Transport Certificate used to + * wrap Private key Archival requests + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class DisplayTransport extends CMSServlet { + + 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 { + + 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; + } + + 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/pki/base/common/src/com/netscape/cms/servlet/key/ExamineRecovery.java b/pki/base/common/src/com/netscape/cms/servlet/key/ExamineRecovery.java new file mode 100644 index 000000000..f92e09714 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/ExamineRecovery.java @@ -0,0 +1,251 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * View the Key Recovery Request + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ExamineRecovery extends CMSServlet { + + 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); + int seq = -1; + + 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 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/pki/base/common/src/com/netscape/cms/servlet/key/GetApprovalStatus.java b/pki/base/common/src/com/netscape/cms/servlet/key/GetApprovalStatus.java new file mode 100644 index 000000000..fc7a812c1 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/GetApprovalStatus.java @@ -0,0 +1,238 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Check to see if a Key Recovery Request has been approved + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetApprovalStatus extends CMSServlet { + + 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 seq = -1; + int rComplete = 0; + + // get status and populate argSet + try { + String recoveryID = req.getParameter("recoveryID"); + + header.addStringValue("recoveryID", recoveryID); + + Hashtable 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 dc = ((IKeyRecoveryAuthority) mService).getAppAgents(recoveryID); + Enumeration agents = dc.elements(); + + while (agents.hasMoreElements()) { + IArgBlock rarg = CMS.createArgBlock(); + + rarg.addStringValue("agentName", ((Credential) 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/pki/base/common/src/com/netscape/cms/servlet/key/GetPk12.java b/pki/base/common/src/com/netscape/cms/servlet/key/GetPk12.java new file mode 100644 index 000000000..1766478a3 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/GetPk12.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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Get the recovered key in PKCS#12 format + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetPk12 extends CMSServlet { + + 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 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(); + + 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); + int seq = -1; + + // get status and populate argSet + try { + String recoveryID = req.getParameter("recoveryID"); + + header.addStringValue("recoveryID", recoveryID); + + Hashtable 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(); + String agent = null; + + 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; + 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])); + } + + 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/pki/base/common/src/com/netscape/cms/servlet/key/GrantRecovery.java b/pki/base/common/src/com/netscape/cms/servlet/key/GrantRecovery.java new file mode 100644 index 000000000..3a3850bb4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/GrantRecovery.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.key; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.base.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Approve a key recovery request + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GrantRecovery extends CMSServlet { + + 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); + + int seq = -1; + + 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 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/pki/base/common/src/com/netscape/cms/servlet/key/KeyRecordParser.java b/pki/base/common/src/com/netscape/cms/servlet/key/KeyRecordParser.java new file mode 100644 index 000000000..1b3748770 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/KeyRecordParser.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.key; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; + +/** + * Output a 'pretty print' of a Key Archival record + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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.addIntegerValue(OUT_SERIALNO, + rec.getSerialNumber().intValue()); + 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/pki/base/common/src/com/netscape/cms/servlet/key/RecoverBySerial.java b/pki/base/common/src/com/netscape/cms/servlet/key/RecoverBySerial.java new file mode 100644 index 000000000..e88abccbe --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/RecoverBySerial.java @@ -0,0 +1,452 @@ +// --- 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 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; +import netscape.security.x509.X509CertImpl; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +/** + * A class representing a recoverBySerial servlet. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class RecoverBySerial extends CMSServlet { + + 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); + + int seq = -1; + + SessionContext ctx = null; + + try { + String localAgents = req.getParameter("localAgents"); + + // this information is needed within the server for + // various signed audit log messages to report + ctx = SessionContext.getContext(); + 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 { + ctx.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); + } + + /** + * 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) { + // 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; + + 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 params = mService.createRecoveryParams(recoveryID); + + params.put("keyID", req.getParameter(IN_SERIALNO)); + + header.addStringValue("recoveryID", recoveryID); + + SessionContext sContext = SessionContext.getContext(); + String agent = null; + + if (sContext != null) { + agent = (String) sContext.get(SessionContext.USER_ID); + } + 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 v = new Vector(); + + 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.addIntegerValue(OUT_SERIALNO, + Integer.parseInt(seq)); + header.addStringValue(OUT_SERVICE_URL, + req.getRequestURI()); + byte pkcs12[] = mService.doKeyRecovery( + new BigInteger(seq), + creds, password, x509cert, + delivery, nickname); + + return pkcs12; + } else { + String recoveryID = req.getParameter("recoveryID"); + + if (recoveryID == null || recoveryID.equals("")) { + header.addStringValue(OUT_ERROR, "No recovery ID specified"); + return null; + } + Hashtable params = mService.createRecoveryParams(recoveryID); + + params.put("keyID", req.getParameter(IN_SERIALNO)); + + header.addStringValue("recoveryID", recoveryID); + + SessionContext sContext = SessionContext.getContext(); + String agent = null; + + if (sContext != null) { + agent = (String) sContext.get(SessionContext.USER_ID); + } + 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; + } + + try { + byte pkcs12[] = mService.doKeyRecovery( + new BigInteger(theSeq), + creds, thePassword, theCert, + theDelivery, theNickname); + + ((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/pki/base/common/src/com/netscape/cms/servlet/key/SrchKey.java b/pki/base/common/src/com/netscape/cms/servlet/key/SrchKey.java new file mode 100644 index 000000000..2a3b31409 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/SrchKey.java @@ -0,0 +1,293 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + +/** + * Retrieve archived keys matching search criteria + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class SrchKey extends CMSServlet { + + 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 e = mKeyDB.searchKeys(filter, + maxResults, timeLimit); + int count = 0; + + if (e == null) { + header.addStringValue(OUT_SENTINEL, + null); + } else { + while (e.hasMoreElements()) { + IKeyRecord rec = (IKeyRecord) + 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/pki/base/common/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java b/pki/base/common/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java new file mode 100644 index 000000000..8ca53b80c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/key/SrchKeyForRecovery.java @@ -0,0 +1,314 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.kra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + +/** + * Retrieve archived keys matching given public key material + * + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class SrchKeyForRecovery extends CMSServlet { + + 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 e = mKeyDB.searchKeys(filter, maxResults, timeLimit); + int count = 0; + + if (e == null) { + header.addStringValue(OUT_SENTINEL, + null); + } else { + while (e.hasMoreElements()) { + IKeyRecord rec = (IKeyRecord) + 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/pki/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java b/pki/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.java new file mode 100644 index 000000000..e4a93826c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/ocsp/AddCAServlet.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.ocsp; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.math.*; +import java.util.Vector; +import java.io.InputStream; +import java.io.IOException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.BIT_STRING; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.util.*; + +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import java.security.cert.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + + +/** + * Configure the CA to respond to OCSP requests for a CA + * + * $Revision: 14561 $ $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class AddCAServlet extends CMSServlet { + + 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; + + 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 + * </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, "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); + + String b64 = cmsReq.getHttpReq().getParameter("cert"); + + if (b64 == null) { + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CA_CERT")); + } + + if (b64.indexOf(BEGIN_HEADER) == -1) { + throw new ECMSGWException(CMS.getUserMessage(getLocale(req), "CMS_GW_MISSING_CERT_HEADER")); + } + if (b64.indexOf(END_HEADER) == -1) { + 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!" ); + throw new EBaseException( "cert is null" ); + } else { + certs = new X509Certificate[1]; + } + + certs[0] = cert; + leafCert = cert; + } 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]; + } + } catch (Exception e) { + 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) { + // error + } + defStore.addCRLIssuingPoint(leafCert.getSubjectDN().getName(), rec); + log(ILogger.EV_AUDIT, AuditFormat.LEVEL, "Added CA certificate " + leafCert.getSubjectDN().getName()); + } + + try { + ServletOutputStream out = resp.getOutputStream(); + String error = null; + + 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/pki/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java b/pki/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java new file mode 100644 index 000000000..dcb4d20ab --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/ocsp/AddCRLServlet.java @@ -0,0 +1,576 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.math.*; +import java.util.Vector; +import java.io.InputStream; +import java.io.IOException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; + +import org.mozilla.jss.*; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.BIT_STRING; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.repository.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.cmsutil.util.*; + +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import java.security.cert.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + + +/** + * Update the OCSP responder with a new CRL + * + * $Revision: 14561 $ $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class AddCRLServlet extends CMSServlet { + + 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; + } + + 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()); + + // update the CRLIssuingPoint record + if (crl == null) { + // error + + // 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")); + } + + 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")); + } + } + + 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/pki/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java b/pki/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java new file mode 100644 index 000000000..f566c1e75 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/ocsp/CheckCertServlet.java @@ -0,0 +1,224 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.Vector; +import java.io.InputStream; +import java.io.IOException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.BIT_STRING; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.authority.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cmsutil.util.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import java.security.cert.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + + +/** + * Check the status of a specific certificate + * + * $Revision: 14561 $ $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CheckCertServlet extends CMSServlet { + + 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 error = null; + + 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/pki/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java b/pki/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.java new file mode 100644 index 000000000..443863759 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/ocsp/GetOCSPInfo.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.ocsp; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.math.*; +import javax.servlet.*; +import java.security.cert.*; +import javax.servlet.http.*; +import netscape.ldap.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; + +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + + +/** + * Retrieve information about the number of OCSP requests the OCSP + * has serviced + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class GetOCSPInfo extends CMSServlet { + 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; + } + + // Construct an ArgBlock + IArgBlock args = cmsReq.getHttpParams(); + + 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/pki/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java b/pki/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java new file mode 100644 index 000000000..1791b1763 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/ocsp/ListCAServlet.java @@ -0,0 +1,211 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.math.*; +import java.util.Vector; +import java.io.InputStream; +import java.io.IOException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.BIT_STRING; + +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.authority.*; +import com.netscape.cmsutil.util.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.apps.*; + +import netscape.security.pkcs.*; +import netscape.security.x509.*; +import java.security.cert.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + + +/** + * Show the list of CA's that the OCSP responder can service + * + * $Revision: 14561 $ $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ListCAServlet extends CMSServlet { + + 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 recs = defStore.searchAllCRLIssuingPointRecord(100); + + // show the current CRL number if present + header.addStringValue("stateCount", + Integer.toString(defStore.getStateCount())); + + while (recs.hasMoreElements()) { + ICRLIssuingPointRecord rec = + (ICRLIssuingPointRecord) 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 error = null; + + 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/pki/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java b/pki/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java new file mode 100644 index 000000000..6a55e88b3 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/ocsp/OCSPServlet.java @@ -0,0 +1,259 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.*; +import java.security.*; +import java.util.Vector; +import java.io.*; +import java.io.InputStream; +import java.io.IOException; +import javax.servlet.ServletConfig; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; + +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.BIT_STRING; + +import netscape.security.x509.*; +import java.security.cert.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.dbs.crldb.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ocsp.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cmsutil.ocsp.*; +import com.netscape.certsrv.base.*; + + +/** + * Process OCSP messages, According to RFC 2560 + * See http://www.ietf.org/rfc/rfc2560.txt + * + * $Revision: 14612 $ $Date: 2007-05-02 17:37:50 -0700 (Wed, 02 May 2007) $ + */ +public class OCSPServlet extends CMSServlet { + + 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(); + java.net.URLDecoder urldecoder = new java.net.URLDecoder(); + if (pathInfo != null && pathInfo.indexOf('%') != -1) { + pathInfo = urldecoder.decode(pathInfo); + } + 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) { + throw new Exception("OCSPServlet: OCSP request not provided in GET method"); + } + is = new ByteArrayInputStream( + com.netscape.osutil.OSUtil.AtoB(pathInfo.substring(1))); + } + + // (1) retrieve OCSP request + // (2) decode request + OCSPResponse response = null; + + try { + OCSPRequest.Template reqTemplate = + new OCSPRequest.Template(); + + ocspReq = (OCSPRequest) reqTemplate.decode(is); + 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/pki/base/common/src/com/netscape/cms/servlet/processors/CMCProcessor.java b/pki/base/common/src/com/netscape/cms/servlet/processors/CMCProcessor.java new file mode 100644 index 000000000..24d6cf1a5 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/processors/CMCProcessor.java @@ -0,0 +1,463 @@ +// --- 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.util.StringTokenizer; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.util.Hashtable; + +import java.io.*; + +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.security.MessageDigest; +import java.security.PublicKey; + + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import netscape.security.util.ObjectIdentifier; +import netscape.security.util.DerValue; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.ChallengeResponseException; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cert.CertificateInfo; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.pkcs11.*; + +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.apps.*; + +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.request.RequestId; + +import com.netscape.certsrv.authentication.*; +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; + +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.base.*; +import java.math.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import com.netscape.cms.servlet.processors.*; + + +/** + * Process CMC messages according to RFC 2797 + * See http://www.ietf.org/rfc/rfc2797.txt + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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 digs = new Hashtable(); + + 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/pki/base/common/src/com/netscape/cms/servlet/processors/CRMFProcessor.java b/pki/base/common/src/com/netscape/cms/servlet/processors/CRMFProcessor.java new file mode 100644 index 000000000..ad8f26c6f --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/processors/CRMFProcessor.java @@ -0,0 +1,370 @@ +// --- 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.cms.servlet.base.*; +import com.netscape.cms.servlet.common.*; + +import java.io.*; + +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; + + +import netscape.security.x509.*; +import netscape.security.util.ObjectIdentifier; + +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.pkix.crmf.*; + +import com.netscape.certsrv.apps.*; + +import com.netscape.certsrv.request.IRequest; + +import com.netscape.certsrv.authentication.*; + +import com.netscape.certsrv.logging.ILogger; + +import com.netscape.certsrv.base.*; + +import com.netscape.cms.servlet.processors.PKIProcessor; + + +/** + * Process CRMF requests, according to RFC 2511 + * See http://www.ietf.org/rfc/rfc2511.txt + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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(); + INTEGER certReqId = certReq.getCertReqId(); + + 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/pki/base/common/src/com/netscape/cms/servlet/processors/IPKIProcessor.java b/pki/base/common/src/com/netscape/cms/servlet/processors/IPKIProcessor.java new file mode 100644 index 000000000..568d84ecb --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/processors/IPKIProcessor.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.processors; + + +import com.netscape.cms.servlet.common.*; +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.util.Hashtable; + +import java.io.*; + +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.security.MessageDigest; +import java.security.PublicKey; + + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import netscape.security.util.ObjectIdentifier; +import netscape.security.util.DerValue; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.ChallengeResponseException; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cert.CertificateInfo; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.pkcs11.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.request.RequestId; + +import com.netscape.certsrv.authentication.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; + +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.base.*; +import java.math.*; + + +/** + * This represents the request parser. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public interface IPKIProcessor { + + public void process(CMSRequest cmsReq) + throws EBaseException; + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java b/pki/base/common/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java new file mode 100644 index 000000000..7d150bf97 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/processors/KeyGenProcessor.java @@ -0,0 +1,185 @@ +// --- 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.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.util.Hashtable; + +import java.io.*; + +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.security.MessageDigest; +import java.security.PublicKey; + + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import netscape.security.util.ObjectIdentifier; +import netscape.security.util.DerValue; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.ChallengeResponseException; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cert.CertificateInfo; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.pkcs11.*; + +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.apps.*; + +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.request.RequestId; + +import com.netscape.certsrv.authentication.*; +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; + +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.base.*; +import java.math.*; + +import com.netscape.cms.servlet.processors.IPKIProcessor; +import com.netscape.cms.servlet.processors.PKIProcessor; + + +/** + * KeyGenProcess parses Certificate request matching the + * KEYGEN tag format used by Netscape Communicator 4.x + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/processors/PKCS10Processor.java b/pki/base/common/src/com/netscape/cms/servlet/processors/PKCS10Processor.java new file mode 100644 index 000000000..18b877a3c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/processors/PKCS10Processor.java @@ -0,0 +1,342 @@ +// --- 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.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.util.Hashtable; + +import java.io.*; + +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.security.MessageDigest; +import java.security.PublicKey; + + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import netscape.security.util.ObjectIdentifier; +import netscape.security.util.DerValue; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.ChallengeResponseException; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cert.CertificateInfo; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.pkcs11.*; + +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.request.RequestId; + +import com.netscape.certsrv.authentication.*; +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; + +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.base.*; +import java.math.*; + +import com.netscape.cms.servlet.processors.IPKIProcessor; +import com.netscape.cms.servlet.processors.PKIProcessor; + + +/** + * PKCS10Processor process Certificate Requests in + * PKCS10 format, as defined here: + * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-10/index.html + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/processors/PKIProcessor.java b/pki/base/common/src/com/netscape/cms/servlet/processors/PKIProcessor.java new file mode 100644 index 000000000..9b6adba80 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/processors/PKIProcessor.java @@ -0,0 +1,417 @@ +// --- 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.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.StringTokenizer; +import java.util.Vector; +import java.util.Enumeration; +import java.util.Date; +import java.util.Hashtable; + +import java.io.*; + +import java.security.InvalidKeyException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; +import java.security.MessageDigest; +import java.security.PublicKey; + + +import netscape.security.util.*; +import netscape.security.x509.*; +import netscape.security.pkcs.*; +import netscape.security.util.ObjectIdentifier; +import netscape.security.util.DerValue; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletOutputStream; +import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; + +import org.mozilla.jss.asn1.SET; +import org.mozilla.jss.asn1.SEQUENCE; +import org.mozilla.jss.asn1.INTEGER; +import org.mozilla.jss.asn1.OCTET_STRING; +import org.mozilla.jss.pkix.crmf.CertTemplate; +import org.mozilla.jss.pkix.crmf.CertReqMsg; +import org.mozilla.jss.pkix.crmf.CertRequest; +import org.mozilla.jss.pkix.crmf.ChallengeResponseException; +import org.mozilla.jss.pkix.primitive.SubjectPublicKeyInfo; +import org.mozilla.jss.pkix.primitive.Name; +import org.mozilla.jss.pkix.primitive.AlgorithmIdentifier; +import org.mozilla.jss.asn1.InvalidBERException; +import org.mozilla.jss.asn1.OBJECT_IDENTIFIER; +import org.mozilla.jss.asn1.ANY; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkcs10.*; +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.pkix.cert.Certificate; +import org.mozilla.jss.pkix.cert.CertificateInfo; +import org.mozilla.jss.asn1.ASN1Util; +import org.mozilla.jss.pkcs11.*; + +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authority.*; + +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.IRequestQueue; +import com.netscape.certsrv.request.RequestStatus; +import com.netscape.certsrv.request.RequestId; + +import com.netscape.certsrv.authentication.*; +import com.netscape.cms.servlet.*; + +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.logging.AuditFormat; + +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.base.*; +import java.math.*; + +import com.netscape.cms.servlet.processors.IPKIProcessor; + + +/** + * Process Certificate Requests + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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(); + + HttpServletRequest httpReq = mRequest.getHttpReq(); + + } + + 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/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java new file mode 100644 index 000000000..25f1adfa4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileApproveServlet.java @@ -0,0 +1,519 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; + + +/** + * Toggle the approval state of a profile + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileApproveServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + private String mAuthorityId = null; + + private final static String LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL = + "LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL_4"; + private final static String OP_APPROVE = "approve"; + private final static String OP_DISAPPROVE = "disapprove"; + + public ProfileApproveServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + } + + /** + * Process the HTTP request. + * <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); + CMS.debug("uid=" + authToken.getInString("userid")); + userid = authToken.getInString("userid"); + } catch (Exception e) { + CMS.debug(e.toString()); + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "approve"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", + e.toString())); + } + + if (authzToken == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + CMS.debug("ProfileApproveServlet: start serving"); + // (1) Read request from the database + + // (2) Get profile id from the request + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileApproveServlet: SubId=" + mProfileSubId); + ps = (IProfileSubsystem) CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileApproveServlet: ProfileSubsystem not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + // retrieve request + IAuthority authority = (IAuthority) CMS.getSubsystem(mAuthorityId); + + if (authority == null) { + CMS.debug("ProfileApproveServlet: Authority " + mAuthorityId + + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + IRequestQueue queue = authority.getRequestQueue(); + + if (queue == null) { + CMS.debug("ProfileApproveServlet: Request Queue of " + + mAuthorityId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + + profileId = request.getParameter("profileId"); + + CMS.debug("ProfileApproveServlet: profileId=" + profileId); + + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + try { + if (ps.isProfileEnable(profileId)) { + if (ps.checkOwner()) { + if (ps.getProfileEnableBy(profileId).equals(userid)) { + ps.disableProfile(profileId); + } else { + // only enableBy can disable profile + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_OWNER")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + } else { + ps.disableProfile(profileId); + } + } else { + ps.enableProfile(profileId, userid); + } + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.SUCCESS, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + } catch (EProfileException e) { + // profile not enabled + CMS.debug("ProfileApproveServlet: profile not error " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + return; + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + auditSubjectID, + ILogger.FAILURE, + auditProfileID, + auditProfileOp); + + audit(auditMessage); + + // rethrow the specific exception to be handled later + throw eAudit1; + // } catch( ServletException eAudit2 ) { + // // store a message in the signed audit log file + // auditMessage = CMS.getLogMessage( + // LOGGING_SIGNED_AUDIT_CERT_PROFILE_APPROVAL, + // auditSubjectID, + // ILogger.FAILURE, + // auditProfileID, + // auditProfileOp ); + // + // audit( auditMessage ); + // + // // rethrow the specific exception to be handled later + // throw eAudit2; + } + + try { + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + // profile not found + CMS.debug("ProfileApproveServlet: profile not found " + + e.toString()); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, e.toString()); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + return; + } + if (profile == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_PROFILE_NOT_FOUND", profileId)); + outputTemplate(request, response, args); + return; + } + + Enumeration policySetIds = profile.getProfilePolicySetIds(); + + ArgList setlist = new ArgList(); + + while (policySetIds.hasMoreElements()) { + String setId = (String) policySetIds.nextElement(); + + Enumeration policyIds = profile.getProfilePolicyIds(setId); + ArgList list = new ArgList(); + + while (policyIds.hasMoreElements()) { + String id = (String) policyIds.nextElement(); + IProfilePolicy policy = (IProfilePolicy) + profile.getProfilePolicy(setId, id); + + // (3) query all the profile policies + // (4) default plugins convert request parameters + // into string http parameters + handlePolicy(list, response, locale, + id, policy); + } + ArgSet setArg = new ArgSet(); + + setArg.set(ARG_POLICY_SET_ID, setId); + setArg.set(ARG_POLICY, list); + setlist.add(setArg); + } + args.set(ARG_POLICY_SET_LIST, setlist); + + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_PROFILE_IS_ENABLED, + Boolean.toString(ps.isProfileEnable(profileId))); + args.set(ARG_PROFILE_ENABLED_BY, ps.getProfileEnableBy(profileId)); + args.set(ARG_PROFILE_NAME, profile.getName(locale)); + args.set(ARG_PROFILE_DESC, profile.getDescription(locale)); + + // (5) return info as template + outputTemplate(request, response, args); + } + + private void handlePolicy(ArgList list, ServletResponse response, + Locale locale, String id, IProfilePolicy policy) { + ArgSet set = new ArgSet(); + + set.set(ARG_POLICY_ID, id); + + // handle default policy + IPolicyDefault def = policy.getDefault(); + String dDesc = def.getText(locale); + + set.set(ARG_DEF_DESC, dDesc); + + ArgList deflist = new ArgList(); + Enumeration defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = (String) defNames.nextElement(); + IDescriptor defDesc = def.getValueDescriptor(locale, defName); + if (defDesc == null) { + CMS.debug("defName=" + defName); + } else { + String defSyntax = defDesc.getSyntax(); + String defConstraint = defDesc.getConstraint(); + String defValueName = defDesc.getDescription(locale); + String defValue = null; + + defset.set(ARG_DEF_ID, defName); + defset.set(ARG_DEF_SYNTAX, defSyntax); + defset.set(ARG_DEF_CONSTRAINT, defConstraint); + defset.set(ARG_DEF_NAME, defValueName); + defset.set(ARG_DEF_VAL, defValue); + deflist.add(defset); + } + } + } + set.set(ARG_DEF_LIST, deflist); + + // handle constraint policy + IPolicyConstraint con = policy.getConstraint(); + String conDesc = con.getText(locale); + + set.set(ARG_CON_DESC, conDesc); + + list.add(set); + } + + /** + * Signed Audit Log Profile ID + * + * This method is called to obtain the "ProfileID" for + * a signed audit log message. + * <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/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java new file mode 100644 index 000000000..3f5a8de91 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileListServlet.java @@ -0,0 +1,169 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import java.util.Enumeration; +import java.util.Locale; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.authorization.AuthzToken; +import com.netscape.certsrv.authorization.EAuthzAccessDenied; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.profile.IProfile; +import com.netscape.certsrv.profile.IProfileSubsystem; +import com.netscape.certsrv.template.ArgList; +import com.netscape.certsrv.template.ArgSet; +import com.netscape.cms.servlet.common.CMSRequest; + + +/** + * List all enabled profiles. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileListServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + + private String mAuthorityId = null; + + public ProfileListServlet() { + super(); + } + + /** + * initialize the servlet. This servlet uses the template file + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + } + + /** + * Process the HTTP request. + * + * @param cmsReq the object holding the request and response information + */ + public void process(CMSRequest cmsReq) throws EBaseException { + HttpServletRequest request = cmsReq.getHttpReq(); + HttpServletResponse response = cmsReq.getHttpResp(); + + CMS.debug("ProfileListServlet: start serving"); + + Locale locale = getLocale(request); + + ArgSet args = new ArgSet(); + IAuthToken authToken = authenticate(cmsReq); + + AuthzToken authzToken = null; + + try { + authzToken = authorize(mAclMethod, authToken, + mAuthzResourceName, "list"); + } catch (EAuthzAccessDenied e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } catch (Exception e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("ADMIN_SRVLT_AUTH_FAILURE", e.toString())); + } + + if (authzToken == null) { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + outputTemplate(request, response, args); + return; + } + + // (1) Read request from the database + + // (2) Get profile id from the request + if (mProfileSubId == null || mProfileSubId.equals("")) { + mProfileSubId = IProfileSubsystem.ID; + } + CMS.debug("ProfileListServlet: SubId=" + mProfileSubId); + IProfileSubsystem ps = (IProfileSubsystem) + CMS.getSubsystem(mProfileSubId); + + if (ps == null) { + CMS.debug("ProfileListServlet: ProfileSubsystem " + + mProfileSubId + " not found"); + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_INTERNAL_ERROR")); + outputTemplate(request, response, args); + return; + } + + ArgList list = new ArgList(); + Enumeration e = ps.getProfileIds(); + + if (e != null) { + while (e.hasMoreElements()) { + String id = (String) e.nextElement(); + IProfile profile = null; + + try { + profile = ps.getProfile(id); + } catch (EBaseException e1) { + // skip bad profile + CMS.debug("ProfileListServlet: profile " + id + + " not found (skipped) " + e1.toString()); + continue; + } + if (profile == null) { + CMS.debug("ProfileListServlet: profile " + id + + " not found (skipped)"); + continue; + } + + String name = profile.getName(locale); + String desc = profile.getDescription(locale); + + ArgSet profileArgs = new ArgSet(); + + profileArgs.set(ARG_PROFILE_IS_ENABLED, + Boolean.toString(ps.isProfileEnable(id))); + profileArgs.set(ARG_PROFILE_ENABLED_BY, + ps.getProfileEnableBy(id)); + profileArgs.set(ARG_PROFILE_ID, id); + profileArgs.set(ARG_PROFILE_IS_VISIBLE, + Boolean.toString(profile.isVisible())); + profileArgs.set(ARG_PROFILE_NAME, name); + profileArgs.set(ARG_PROFILE_DESC, desc); + list.add(profileArgs); + + } + } + args.set(ARG_RECORD, list); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + // (5) return info as template + outputTemplate(request, response, args); + } + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java new file mode 100644 index 000000000..dcbca5e3b --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileProcessServlet.java @@ -0,0 +1,893 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; + +import java.security.cert.*; +import netscape.security.x509.*; + + +/** + * This servlet approves profile-based request. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileProcessServlet extends ProfileServlet { + private static final String PROP_AUTHORITY_ID = "authorityId"; + private String mAuthorityId = null; + + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + 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); + } + + 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; + } + + 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)); + 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 { + 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 outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput( + outputId); + + Enumeration outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = (String) + outputNames.nextElement(); + IDescriptor outputDesc = + profileOutput.getValueDescriptor(locale, + outputName); + + if (outputDesc == null) + continue; + String outputSyntax = outputDesc.getSyntax(); + String outputConstraint = + outputDesc.getConstraint(); + String outputValueName = + outputDesc.getDescription(locale); + String outputValue = null; + + try { + outputValue = profileOutput.getValue( + outputName, + locale, req); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: " + + e.toString()); + } + + outputset.set(ARG_OUTPUT_ID, outputName); + outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax); + outputset.set(ARG_OUTPUT_CONSTRAINT, + outputConstraint); + outputset.set(ARG_OUTPUT_NAME, outputValueName); + outputset.set(ARG_OUTPUT_VAL, outputValue); + outputlist.add(outputset); + } + } + } + } + args.set(ARG_OUTPUT_LIST, outputlist); + + // retrieve the certificate + X509CertImpl theCert = req.getExtDataInCert( + IEnrollProfile.REQUEST_ISSUED_CERT); + + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.SUCCESS, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + auditInfoCertValue(theCert)); + + audit(auditMessage); + + } catch (EProfileException eAudit1) { + // store a message in the signed audit log file + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_ACCEPTANCE, + ILogger.SIGNED_AUDIT_EMPTY_VALUE); + + audit(auditMessage); + + CMS.debug("ProfileProcessServlet: about to throw EProfileException because of bad profile execute."); + throw new EProfileException(eAudit1.toString()); + + + } + } + + protected void updateValues(ServletRequest request, IRequest req, + IRequestQueue queue, IProfile profile, Locale locale) + throws ERejectException, EDeferException, EPropertyException { + String profileSetId = req.getExtDataInString("profileSetId"); + + Enumeration policies = profile.getProfilePolicies(profileSetId); + int count = 0; + + while (policies.hasMoreElements()) { + IProfilePolicy policy = (IProfilePolicy) policies.nextElement(); + + setValue(locale, count, policy, req, request); + count++; + } + + policies = profile.getProfilePolicies(profileSetId); + count = 0; + while (policies.hasMoreElements()) { + IProfilePolicy policy = (IProfilePolicy) policies.nextElement(); + + validate(locale, count, policy, req, request); + count++; + } + + } + + protected void updateNotes(ServletRequest request, IRequest req) { + String notes = request.getParameter(ARG_REQUEST_NOTES); + + if (notes != null) { + req.setExtData("requestNotes", notes); + } + } + + protected void validate(Locale locale, int count, + IProfilePolicy policy, IRequest req, ServletRequest request) + throws ERejectException, EDeferException { + IPolicyConstraint con = policy.getConstraint(); + + con.validate(req); + } + + protected void setValue(Locale locale, int count, + IProfilePolicy policy, IRequest req, ServletRequest request) + throws EPropertyException { + // handle default policy + IPolicyDefault def = policy.getDefault(); + Enumeration defNames = def.getValueNames(); + + while (defNames.hasMoreElements()) { + String defName = (String) defNames.nextElement(); + String defValue = request.getParameter(defName); + + def.setValue(defName, locale, req, defValue); + } + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <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 = com.netscape.osutil.OSUtil.BtoA(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (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/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java new file mode 100644 index 000000000..50ca8ba2d --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileReviewServlet.java @@ -0,0 +1,414 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import java.io.*; +import java.util.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; + + +/** + * This servlet allows reviewing of profile-based request. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileReviewServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + + private String mAuthorityId = 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); + } + + /** + * 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 policyIds = profile.getProfilePolicyIds(profileSetId); + int count = 0; + ArgList list = new ArgList(); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = (String) policyIds.nextElement(); + IProfilePolicy policy = (IProfilePolicy) + profile.getProfilePolicy(req.getExtDataInString("profileSetId"), + id); + + // (3) query all the profile policies + // (4) default plugins convert request parameters into string + // http parameters + handlePolicy(list, response, locale, + id, policy, req); + count++; + } + } + args.set(ARG_REQUEST_ID, req.getRequestId().toString()); + args.set(ARG_REQUEST_TYPE, req.getRequestType()); + args.set(ARG_REQUEST_STATUS, req.getRequestStatus().toString()); + if (req.getRequestOwner() == null) { + args.set(ARG_REQUEST_OWNER, ""); + } else { + args.set(ARG_REQUEST_OWNER, req.getRequestOwner()); + } + args.set(ARG_REQUEST_CREATION_TIME, req.getCreationTime().toString()); + args.set(ARG_REQUEST_MODIFICATION_TIME, + req.getModificationTime().toString()); + + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_PROFILE_APPROVED_BY, + req.getExtDataInString("profileApprovedBy")); + args.set(ARG_PROFILE_SET_ID, req.getExtDataInString("profileSetId")); + if (profile.isVisible()) { + args.set(ARG_PROFILE_IS_VISIBLE, "true"); + } else { + args.set(ARG_PROFILE_IS_VISIBLE, "false"); + } + args.set(ARG_PROFILE_NAME, profile.getName(locale)); + args.set(ARG_PROFILE_DESC, profile.getDescription(locale)); + args.set(ARG_PROFILE_REMOTE_HOST, + req.getExtDataInString("profileRemoteHost")); + args.set(ARG_PROFILE_REMOTE_ADDR, + req.getExtDataInString("profileRemoteAddr")); + if (req.getExtDataInString("requestNotes") == null) { + args.set(ARG_REQUEST_NOTES, ""); + } else { + args.set(ARG_REQUEST_NOTES, + req.getExtDataInString("requestNotes")); + } + + args.set(ARG_RECORD, list); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + ArgList inputlist = new ArgList(); + + // populate authentication parameters + + // populate input parameters + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + ArgSet inputset = new ArgSet(); + String inputName = (String) inputNames.nextElement(); + + IDescriptor inputDesc = profileInput.getValueDescriptor(locale, inputName); + + if (inputDesc == null) + continue; + String inputSyntax = inputDesc.getSyntax(); + String inputConstraint = inputDesc.getConstraint(); + String inputValueName = inputDesc.getDescription(locale); + String inputValue = null; + + try { + inputValue = profileInput.getValue(inputName, locale, req); + } catch (EBaseException e) { + CMS.debug("ProfileReviewServlet: " + e.toString()); + } + + inputset.set(ARG_INPUT_ID, inputName); + inputset.set(ARG_INPUT_SYNTAX, inputSyntax); + inputset.set(ARG_INPUT_CONSTRAINT, inputConstraint); + inputset.set(ARG_INPUT_NAME, inputValueName); + inputset.set(ARG_INPUT_VAL, inputValue); + inputlist.add(inputset); + } + } + } + } + args.set(ARG_INPUT_LIST, inputlist); + + // if request in complete state + + ArgList outputlist = new ArgList(); + Enumeration outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId + ); + + Enumeration outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = (String) outputNames.nextElement + (); + IDescriptor outputDesc = + profileOutput.getValueDescriptor(locale, outputName); + + if (outputDesc == null) + continue; + String outputSyntax = outputDesc.getSyntax(); + String outputConstraint = outputDesc.getConstraint(); + String outputValueName = outputDesc.getDescription(locale); + String outputValue = null; + + try { + outputValue = profileOutput.getValue(outputName, + locale, req); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: " + e.toString( + )); + } + + outputset.set(ARG_OUTPUT_ID, outputName); + outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax); + outputset.set(ARG_OUTPUT_CONSTRAINT, outputConstraint); + outputset.set(ARG_OUTPUT_NAME, outputValueName); + outputset.set(ARG_OUTPUT_VAL, outputValue); + outputlist.add(outputset); + } + } + } + } + args.set(ARG_OUTPUT_LIST, outputlist); + + // (5) return info as template + outputTemplate(request, response, args); + } + + private void handlePolicy(ArgList list, ServletResponse response, + Locale locale, String id, IProfilePolicy policy, + IRequest req) { + ArgSet set = new ArgSet(); + + set.set(ARG_POLICY_ID, id); + + // handle default policy + IPolicyDefault def = policy.getDefault(); + String dDesc = def.getText(locale); + + set.set(ARG_DEF_DESC, dDesc); + ArgList deflist = new ArgList(); + Enumeration defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = (String) defNames.nextElement(); + IDescriptor defDesc = def.getValueDescriptor(locale, defName); + + if (defDesc == null) + continue; + String defSyntax = defDesc.getSyntax(); + String defConstraint = defDesc.getConstraint(); + String defValueName = defDesc.getDescription(locale); + String defValue = null; + + try { + defValue = def.getValue(defName, locale, req); + } catch (EPropertyException ee) { + CMS.debug("ProfileReviewServlet: " + ee.toString()); + } + + defset.set(ARG_DEF_ID, defName); + defset.set(ARG_DEF_SYNTAX, defSyntax); + defset.set(ARG_DEF_CONSTRAINT, defConstraint); + defset.set(ARG_DEF_NAME, defValueName); + defset.set(ARG_DEF_VAL, defValue); + deflist.add(defset); + } + } + set.set(ARG_DEF_LIST, deflist); + + // handle constraint policy + IPolicyConstraint con = policy.getConstraint(); + + if (con != null) { + String conDesc = con.getText(locale); + + set.set(ARG_CON_DESC, conDesc); + } + + list.add(set); + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java new file mode 100644 index 000000000..83904279c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSelectServlet.java @@ -0,0 +1,387 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import com.netscape.cms.servlet.common.*; + +import java.io.*; +import java.util.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; + +import netscape.security.x509.*; + + +/** + * Retrieve detailed information of a particular profile. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileSelectServlet extends ProfileServlet { + + private static final String PROP_AUTHORITY_ID = "authorityId"; + private String mAuthorityId = null; + + public ProfileSelectServlet() { + } + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + } + + /** + * Process the HTTP request. + * <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 policySetIds = profile.getProfilePolicySetIds(); + + if (policySetIds != null) { + while (policySetIds.hasMoreElements()) { + String setId = (String) policySetIds.nextElement(); + + ArgList list = new ArgList(); + Enumeration policyIds = profile.getProfilePolicyIds(setId); + + if (policyIds != null) { + while (policyIds.hasMoreElements()) { + String id = (String) policyIds.nextElement(); + IProfilePolicy policy = (IProfilePolicy) + profile.getProfilePolicy(setId, id); + + // (3) query all the profile policies + // (4) default plugins convert request parameters into string + // http parameters + handlePolicy(list, response, locale, + id, policy); + } + } + ArgSet setArg = new ArgSet(); + + setArg.set(ARG_POLICY_SET_ID, setId); + setArg.set(ARG_POLICY, list); + setlist.add(setArg); + } + } + args.set(ARG_POLICY_SET_LIST, setlist); + + args.set(ARG_PROFILE_ID, profileId); + args.set(ARG_PROFILE_IS_ENABLED, + Boolean.toString(ps.isProfileEnable(profileId))); + args.set(ARG_PROFILE_ENABLED_BY, ps.getProfileEnableBy(profileId)); + args.set(ARG_PROFILE_NAME, profile.getName(locale)); + args.set(ARG_PROFILE_DESC, profile.getDescription(locale)); + args.set(ARG_PROFILE_IS_VISIBLE, + Boolean.toString(profile.isVisible())); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + try { + boolean keyArchivalEnabled = CMS.getConfigStore().getBoolean("ca.connector.KRA.enable", false); + if (keyArchivalEnabled == true) { + CMS.debug("ProfileSelectServlet: keyArchivalEnabled is true"); + + // output transport certificate if present + args.set("transportCert", + CMS.getConfigStore().getString("ca.connector.KRA.transportCert", "")); + } else { + CMS.debug("ProfileSelectServlet: keyArchivalEnabled is false"); + args.set("transportCert", ""); + } + } catch (EBaseException e) { + CMS.debug("ProfileSelectServlet: exception caught:"+e.toString()); + } + + // build authentication + ArgList authlist = new ArgList(); + IProfileAuthenticator authenticator = null; + + try { + authenticator = profile.getAuthenticator(); + } catch (EProfileException e) { + // authenticator not installed correctly + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_MANAGER_NOT_FOUND", + profile.getAuthenticatorId())); + outputTemplate(request, response, args); + return; + } + + if (authenticator != null) { + Enumeration authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + ArgSet authset = new ArgSet(); + String authName = (String) authNames.nextElement(); + IDescriptor authDesc = + authenticator.getValueDescriptor(locale, authName); + + if (authDesc == null) + continue; + String authSyntax = authDesc.getSyntax(); + String authConstraint = authDesc.getConstraint(); + String authValueName = authDesc.getDescription(locale); + + authset.set(ARG_AUTH_ID, authName); + authset.set(ARG_AUTH_SYNTAX, authSyntax); + authset.set(ARG_AUTH_CONSTRAINT, authConstraint); + authset.set(ARG_AUTH_NAME, authValueName); + authlist.add(authset); + } + } + args.set(ARG_AUTH_LIST, authlist); + args.set(ARG_AUTH_NAME, authenticator.getName(locale)); + args.set(ARG_AUTH_DESC, authenticator.getText(locale)); + args.set(ARG_AUTH_IS_SSL, + Boolean.toString(authenticator.isSSLClientRequired())); + } + + // build input list + ArgList inputlist = new ArgList(); + ArgList inputPluginlist = new ArgList(); + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + + if (profileInput != null) { + + ArgSet inputpluginset = new ArgSet(); + inputpluginset.set(ARG_INPUT_PLUGIN_ID, inputId); + inputpluginset.set(ARG_INPUT_PLUGIN_NAME, + profileInput.getName(locale)); + inputpluginset.set(ARG_INPUT_PLUGIN_DESC, + profileInput.getText(locale)); + inputPluginlist.add(inputpluginset); + + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + ArgSet inputset = new ArgSet(); + String inputName = (String) inputNames.nextElement(); + IDescriptor inputDesc = profileInput.getValueDescriptor( + locale, inputName); + + if (inputDesc == null) + continue; + String inputSyntax = inputDesc.getSyntax(); + String inputConstraint = inputDesc.getConstraint(); + String inputValueName = inputDesc.getDescription(locale); + String inputValue = null; + + inputset.set(ARG_INPUT_PLUGIN_ID, inputId); + inputset.set(ARG_INPUT_ID, inputName); + inputset.set(ARG_INPUT_SYNTAX, inputSyntax); + inputset.set(ARG_INPUT_CONSTRAINT, inputConstraint); + inputset.set(ARG_INPUT_NAME, inputValueName); + inputset.set(ARG_INPUT_VAL, inputValue); + inputlist.add(inputset); + } + } + } + } + } + args.set(ARG_INPUT_LIST, inputlist); + args.set(ARG_INPUT_PLUGIN_LIST, inputPluginlist); + + // (5) return info as template + outputTemplate(request, response, args); + } + + private void handlePolicy(ArgList list, ServletResponse response, + Locale locale, String id, IProfilePolicy policy) { + ArgSet set = new ArgSet(); + + set.set(ARG_POLICY_ID, id); + + // handle default policy + IPolicyDefault def = policy.getDefault(); + String dDesc = def.getText(locale); + + set.set(ARG_DEF_DESC, dDesc); + ArgList deflist = new ArgList(); + Enumeration defNames = def.getValueNames(); + + if (defNames != null) { + while (defNames.hasMoreElements()) { + ArgSet defset = new ArgSet(); + String defName = (String) defNames.nextElement(); + IDescriptor defDesc = def.getValueDescriptor(locale, defName); + + if (defDesc == null) + continue; + String defSyntax = defDesc.getSyntax(); + String defConstraint = defDesc.getConstraint(); + String defValueName = defDesc.getDescription(locale); + String defValue = null; + + defset.set(ARG_DEF_ID, defName); + defset.set(ARG_DEF_SYNTAX, defSyntax); + defset.set(ARG_DEF_CONSTRAINT, defConstraint); + defset.set(ARG_DEF_NAME, defValueName); + defset.set(ARG_DEF_VAL, defValue); + deflist.add(defset); + } + } + set.set(ARG_DEF_LIST, deflist); + + // handle constraint policy + IPolicyConstraint con = policy.getConstraint(); + String conDesc = con.getText(locale); + + set.set(ARG_CON_DESC, conDesc); + + list.add(set); + } + +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java new file mode 100644 index 000000000..0aa6155a6 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileServlet.java @@ -0,0 +1,462 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.util.*; +import java.io.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.authentication.AuthCredentials; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.logging.*; + +import netscape.security.x509.*; + + +/** + * This servlet is the base class of all profile servlets. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileServlet extends CMSServlet { + + public final static String ARG_ERROR_CODE = "errorCode"; + public final static String ARG_ERROR_REASON = "errorReason"; + public final static String ARG_RECORD = "record"; + public final static String ARG_OP = "op"; + + public final static String ARG_REQUEST_LIST = "requestList"; + public final static String ARG_REQUEST_ID = "requestId"; + public final static String ARG_REQUEST_TYPE = "requestType"; + public final static String ARG_REQUEST_STATUS = "requestStatus"; + public final static String ARG_REQUEST_OWNER = + "requestOwner"; + public final static String ARG_REQUEST_CREATION_TIME = + "requestCreationTime"; + public final static String ARG_REQUEST_MODIFICATION_TIME = + "requestModificationTime"; + + public final static String ARG_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_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_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_OUTPUT_LIST = "outputList"; + public final static String ARG_OUTPUT_ID = "outputId"; + public final static String ARG_OUTPUT_SYNTAX = "outputSyntax"; + public final static String ARG_OUTPUT_CONSTRAINT = "outputConstraint"; + public final static String ARG_OUTPUT_NAME = "outputName"; + public final static String ARG_OUTPUT_VAL = "outputVal"; + + private static final String PROP_TEMPLATE = "templatePath"; + private static final String PROP_AUTH_MGR_ID = "authMgrId"; + private final static String PROP_AUTHMGR = "AuthMgr"; + private final static String PROP_CLIENTAUTH = "GetClientCert"; + private static final String PROP_PROFILE_SUB_ID = "profileSubId"; + private static final String PROP_ID = "ID"; + public final static String PROP_RESOURCEID = "resourceID"; + public final static String AUTHZ_SRC_LDAP = "ldap"; + public final static String AUTHZ_SRC_TYPE = "sourceType"; + public final static String AUTHZ_CONFIG_STORE = "authz"; + public final static String AUTHZ_SRC_XML = "web.xml"; + public final static String PROP_AUTHZ_MGR = "AuthzMgr"; + public final static String PROP_ACL = "ACLinfo"; + public final static String AUTHZ_MGR_BASIC = "BasicAclAuthz"; + public final static String AUTHZ_MGR_LDAP = "DirAclAuthz"; + + private final static String HDR_LANG = "accept-language"; + + private String mTemplate = null; + private String mAuthMgrId = null; + + protected String mId = null; + protected String mGetClientCert = "false"; + protected String mAuthMgr = null; + protected IAuthzSubsystem mAuthz = null; + protected String mAclMethod = null; + protected String mAuthzResourceName = null; + protected ILogger mLogger = CMS.getLogger(); + protected int mLogCategory = ILogger.S_OTHER; + protected String mProfileSubId = null; + + protected ILogger mSignedAuditLogger = CMS.getSignedAuditLogger(); + + public ProfileServlet() { + super(); + } + + /** + * initialize the servlet. Servlets implementing this method + * must specify the template to use as a parameter called + * "templatePath" in the servletConfig + * + * @param sc servlet configuration, read from the web.xml file + */ + + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mTemplate = sc.getServletContext().getRealPath( + sc.getInitParameter(PROP_TEMPLATE)); + mGetClientCert = sc.getInitParameter(PROP_CLIENTAUTH); + mAuthMgr = sc.getInitParameter(PROP_AUTHMGR); + mAuthz = (IAuthzSubsystem) CMS.getSubsystem(CMS.SUBSYSTEM_AUTHZ); + mAuthzResourceName = sc.getInitParameter(PROP_RESOURCEID); + mProfileSubId = sc.getInitParameter(PROP_PROFILE_SUB_ID); + mId = sc.getInitParameter(PROP_ID); + + try { + mAclMethod = Utils.initializeAuthz(sc, mAuthz, mId); + } catch (ServletException e) { + log(ILogger.LL_FAILURE, e.toString()); + throw e; + } + } + + protected String escapeXML(String v) + { + if (v == null) { + return ""; + } + v = v.replaceAll("&", "&"); + return v; + } + + protected void outputArgValueAsXML(PrintStream ps, String name, IArgValue v) + { + ps.println("<" + name + ">"); + if (v != null) { + if (v instanceof ArgList) { + ArgList list = (ArgList)v; + ps.println("<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 names = set.getNames(); + while (names.hasMoreElements()) { + String n = (String)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"); + + 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 * 2]; + int j = 0; + + v.getChars(0, l, in, 0); + + for (int i = 0; i < l; i++) { + char c = in[i]; + + if (c > 0x23) { + out[j++] = c; + 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; + + default: + out[j++] = c; + } + } + return new String(out, 0, j); + } + + protected void outputArgString(PrintWriter writer, String name, ArgString str) + throws IOException { + String s = str.getValue(); + + // sub \n with "\n" + if (s != null) { + s = escapeJavaScriptString(s); + } + writer.println(name + "=\"" + s + "\";"); + } + + protected void outputArgSet(PrintWriter writer, String name, ArgSet set) + throws IOException { + Enumeration e = set.getNames(); + + while (e.hasMoreElements()) { + String n = (String) e.nextElement(); + IArgValue val = set.get(n); + + if (val instanceof ArgSet) { + ArgSet set1 = (ArgSet) val; + + outputArgSet(writer, name + "." + n, set1); + } else if (val instanceof ArgList) { + ArgList list = (ArgList) val; + + outputArgList(writer, name + "." + n, list); + } else if (val instanceof ArgString) { + ArgString str = (ArgString) val; + + outputArgString(writer, name + "." + n, str); + } + } + } + + protected void outputData(PrintWriter writer, ArgSet set) + throws IOException { + if (set == null) + return; + Enumeration e = set.getNames(); + + while (e.hasMoreElements()) { + String n = (String) e.nextElement(); + IArgValue val = set.get(n); + + if (val instanceof ArgSet) { + ArgSet set1 = (ArgSet) val; + + outputArgSet(writer, n, set1); + } else if (val instanceof ArgList) { + ArgList list = (ArgList) val; + + outputArgList(writer, n, list); + } else if (val instanceof ArgString) { + ArgString str = (ArgString) val; + + outputArgString(writer, n, str); + } + } + } + + /** + * log according to authority category. + */ + protected void log(int event, int level, String msg) { + mLogger.log(event, mLogCategory, level, + "Servlet " + mId + ": " + msg); + } + + protected void log(int level, String msg) { + mLogger.log(ILogger.EV_SYSTEM, mLogCategory, level, + "Servlet " + mId + ": " + msg); + } + + /** + * Retrieves locale based on the request. + */ + protected Locale getLocale(HttpServletRequest req) { + Locale locale = null; + String lang = req.getHeader(HDR_LANG); + + if (lang == null) { + // use server locale + locale = Locale.getDefault(); + } else { + locale = new Locale(UserInfo.getUserLanguage(lang), + UserInfo.getUserCountry(lang)); + } + return locale; + } + + protected void renderResult(CMSRequest cmsReq) + throws IOException { + // do nothing + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java new file mode 100644 index 000000000..aa0affaca --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitCMCServlet.java @@ -0,0 +1,823 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import java.util.*; +import java.security.cert.*; +import java.io.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.common.AuthCredentials; +import org.mozilla.jss.asn1.*; +import org.mozilla.jss.pkix.cmc.*; + +import netscape.security.x509.*; + + +/** + * This servlet submits end-user request into the profile framework. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileSubmitCMCServlet extends ProfileServlet { + + private static final String ARG_AUTH_TOKEN = "auth_token"; + private static final String PROP_PROFILE_ID = "profileId"; + private static final String PROP_AUTHORITY_ID = "authorityId"; + + private String mOutputTemplateClassName = null; + private String mProfileId = null; + private String mProfileSubId = null; + private String mReqType = null; + private String mAuthorityId = null; + private String requestBinary = null; + private String requestB64 = null; + + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + private final static String[] + SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] { + + /* 0 */ "automated profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException" + }; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + public ProfileSubmitCMCServlet() { + } + + /** + * initialize the servlet. And instance of this servlet can + * be set up to always issue certificates against a certain profile + * by setting the 'profileId' configuration in the servletConfig + * If not, the user must specify the profileID when submitting the request + * + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + mProfileId = sc.getInitParameter(PROP_PROFILE_ID); + mOutputTemplateClassName = sc.getInitParameter("outputTemplateClass"); + mRenderResult = false; + } + + private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) { + + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + ctx.set(inputName, request.getParameter(inputName)); + } + } + } + } + + } + + private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, IProfileContext ctx) { + Enumeration authIds = authenticator.getValueNames(); + + if (authIds != null) { + while (authIds.hasMoreElements()) { + String authName = (String) authIds.nextElement(); + + if (request.getParameter(authName) != null) { + ctx.set(authName, request.getParameter(authName)); + } + } + } + } + + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + AuthCredentials credentials = new AuthCredentials(); + + // build credential + Enumeration authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = (String) authNames.nextElement(); + + if (authName.equals("cert_request")) + credentials.set(authName, requestB64); + else + credentials.set(authName, request.getParameter(authName)); + } + } + IAuthToken authToken = authenticator.authenticate(credentials); + + SessionContext sc = SessionContext.getContext(); + if (sc != null) { + sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName()); + String userid = authToken.getInString(IAuthToken.USER_ID); + if (userid != null) { + sc.put(SessionContext.USER_ID, userid); + } + } + + return authToken; + } + + private void setInputsIntoRequest(HttpServletRequest request, IProfile +profile, IRequest req) { + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + req.setExtData(inputName, request.getParameter(inputName)); + } + } + } + } + } + } + + /** + * Process the HTTP request + * <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); + ArgSet args = new ArgSet(); + String cert_request_type = + mServletConfig.getInitParameter("cert_request_type"); + String outputFormat = mServletConfig.getInitParameter("outputFormat"); + + int reqlen = request.getContentLength(); + InputStream is = null; + try { + is = request.getInputStream(); + } catch (Exception ee) { + } + byte reqbuf[] = new byte[reqlen]; + int bytesread = 0; + boolean partial = false; + + while (bytesread < reqlen) { + try { + bytesread += is.read(reqbuf, bytesread, reqlen - bytesread); + } catch (Exception ee) { + } + + if (partial == false) { + if (bytesread < reqlen) + partial = true; + } + } + + requestB64 = com.netscape.osutil.OSUtil.BtoA(reqbuf); + + if (CMS.debugOn()) { + CMS.debug("Start of Input Parameters"); + Enumeration paramNames = request.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String paramName = (String) paramNames.nextElement(); + + CMS.debug("Input Parameter " + paramName + "='" + + request.getParameter(paramName) + "'"); + } + CMS.debug("End of 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"); + 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("ProfileSubmitServlet: profileId " + profileId); + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: 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("ProfileSubmitServlet: 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("ProfileSubmitServlet: authenticator not found"); + } else { + CMS.debug("ProfileSubmitServlet: 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("ProfileSubmitServlet: 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("ProfileSubmitServlet: authentication error " + + e.toString()); + return; + } + } + + IRequest reqs[] = null; + + /////////////////////////////////////////////// + // create request + /////////////////////////////////////////////// + try { + reqs = profile.createRequests(ctx, locale); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: 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("ProfileSubmitServlet: createRequests " + e.toString()); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(CMS.getUserMessage(locale, "CMS_INTERNAL_ERROR")); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + + TaggedAttribute attr = + (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_lraPOPWitness)); + if (attr != null) { + boolean verifyAllow = true; + try { + verifyAllow = CMS.getConfigStore().getBoolean( + "cmc.lraPopWitness.verify.allow", true); + } catch (EBaseException ee) { + } + + if (!verifyAllow) { + LraPopWitness lraPop = null; + SET vals = attr.getValues(); + if (vals.size() > 0) { + try { + lraPop = (LraPopWitness)(ASN1Util.decode(LraPopWitness.getTemplate(), + ASN1Util.encode(vals.elementAt(0)))); + } catch (InvalidBERException e) { + CMS.debug( + CMS.getUserMessage(locale, "CMS_PROFILE_ENCODING_ERROR")); + } + + SEQUENCE bodyIds = lraPop.getBodyIds(); + + CMCOutputTemplate template = new CMCOutputTemplate(); + template.createFullResponseWithFailedStatus(response, bodyIds, + OtherInfo.POP_FAILED, null); + return; + } + } + } + + // for CMC, requests may be zero. Then check if controls exist. + if (reqs == null) { + Integer nums = (Integer)(context.get("numOfControls")); + CMCOutputTemplate template = new CMCOutputTemplate(); + // if there is only one control GetCert, then simple response + // must be returned. + if (nums != null && nums.intValue() == 1) { + TaggedAttribute attr1 = (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_getCert)); + if (attr1 != null) { + template.createSimpleResponse(response, reqs); + } else + template.createFullResponse(response, reqs, + cert_request_type, null); + } else + template.createFullResponse(response, reqs, + cert_request_type, null); + return; + } + + String errorCode = null; + String errorReason = null; + + /////////////////////////////////////////////// + // populate request + /////////////////////////////////////////////// + for (int k = 0; k < reqs.length; k++) { + // adding parameters to request + setInputsIntoRequest(request, profile, reqs[k]); + + // serial auth token into request + if (authToken != null) { + Enumeration tokenNames = authToken.getElements(); + while (tokenNames.hasMoreElements()) { + String tokenName = (String)tokenNames.nextElement(); + String[] vals = authToken.getInStringArray(tokenName); + if (vals != null) { + for (int i = 0; i < vals.length; i++) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + + tokenName + "[" + i + "]", vals[i]); + } + } else { + String val = authToken.getInString(tokenName); + if (val != null) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + tokenName, + val); + } + } + } + } + + // put profile framework parameters into the request + reqs[k].setExtData(ARG_PROFILE, "true"); + reqs[k].setExtData(ARG_PROFILE_ID, profileId); + reqs[k].setExtData(ARG_PROFILE_APPROVED_BY, profile.getApprovedBy()); + String setId = profile.getPolicySetId(reqs[k]); + + if (setId == null) { + // no profile set found + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND")); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + + CMS.debug("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()); + 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("ProfileSubmitServlet: populate " + e.toString()); + // throw new IOException("Profile " + profileId + + // " cannot populate"); + CMCOutputTemplate template = new CMCOutputTemplate(); + SEQUENCE seq = new SEQUENCE(); + seq.addElement(new INTEGER(0)); + UTF8String s = null; + try { + s = new UTF8String(e.toString()); + } catch (Exception ee) { + } + template.createFullResponseWithFailedStatus(response, seq, + OtherInfo.INTERNAL_CA_ERROR, s); + return; + } + } + + String auditMessage = null; + String auditSubjectID = auditSubjectID(); + String auditRequesterID = ILogger.UNIDENTIFIED; + String auditInfoCertValue = ILogger.SIGNED_AUDIT_EMPTY_VALUE; + + int responseType = 0; + try { + /////////////////////////////////////////////// + // submit request + /////////////////////////////////////////////// + int error_codes[] = null; + if (reqs != null && reqs.length > 0) + error_codes = new int[reqs.length]; + for (int k = 0; k < reqs.length; k++) { + try { + // reset the "auditRequesterID" + auditRequesterID = auditRequesterID(reqs[k]); + + + // print request debug + if (reqs[k] != null) { + Enumeration reqKeys = reqs[k].getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = (String)reqKeys.nextElement(); + String reqVal = reqs[k].getExtDataInString(reqKey); + if (reqVal != null) { + CMS.debug("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 { + 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); + } + 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("ProfileSubmitServlet: done serving"); + CMCOutputTemplate template = new CMCOutputTemplate(); + if (cert_request_type.equals("pkcs10") || cert_request_type.equals("crmf")) { + + if (outputFormat != null &&outputFormat.equals("pkcs7")) { + byte[] pkcs7 = CMS.getPKCS7(locale, reqs[0]); + response.setContentType("application/pkcs7-mime"); + response.setContentLength(pkcs7.length); + try { + OutputStream os = response.getOutputStream(); + os.write(pkcs7); + os.flush(); + } catch (Exception ee) { + } + return; + } + template.createSimpleResponse(response, reqs); + } else if (cert_request_type.equals("cmc")) { + Integer nums = (Integer)(context.get("numOfControls")); + if (nums != null && nums.intValue() == 1) { + TaggedAttribute attr1 = + (TaggedAttribute)(context.get(OBJECT_IDENTIFIER.id_cmc_getCert)); + if (attr1 != null) { + template.createSimpleResponse(response, reqs); + return; + } + } + template.createFullResponse(response, reqs, cert_request_type, + error_codes); + } + } finally { + context.releaseContext(); + } + } + + /** + * Signed Audit Log Requester ID + * + * This method is called to obtain the "RequesterID" for + * a signed audit log message. + * <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 = com.netscape.osutil.OSUtil.BtoA(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (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/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java new file mode 100644 index 000000000..693e04fb4 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/ProfileSubmitServlet.java @@ -0,0 +1,945 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + + +import java.util.*; +import java.security.cert.*; +import javax.servlet.*; +import javax.servlet.http.*; + +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.util.*; +import com.netscape.certsrv.template.*; +import com.netscape.certsrv.property.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.logging.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.common.AuthCredentials; +import com.netscape.cmsutil.xml.*; +import com.netscape.cmsutil.util.*; +import org.w3c.dom.*; +import netscape.security.x509.*; + + +/** + * This servlet submits end-user request into the profile framework. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProfileSubmitServlet extends ProfileServlet { + + private static final String ARG_AUTH_TOKEN = "auth_token"; + private static final String ARG_REQUEST_OWNER = "requestOwner"; + private static final String PROP_PROFILE_ID = "profileId"; + private static final String PROP_AUTHORITY_ID = "authorityId"; + private final static String SUCCESS = "0"; + private final static String FAILED = "1"; + + private String mProfileId = null; + private String mProfileSubId = null; + private String mReqType = null; + private String mAuthorityId = null; + + private final static byte EOL[] = { Character.LINE_SEPARATOR }; + private final static String[] + SIGNED_AUDIT_AUTOMATED_REJECTION_REASON = new String[] { + + /* 0 */ "automated profile cert request rejection: " + + "indeterminate reason for inability to process " + + "cert request due to an EBaseException" + }; + private final static String LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED = + "LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED_5"; + + public ProfileSubmitServlet() { + } + + /** + * initialize the servlet. And instance of this servlet can + * be set up to always issue certificates against a certain profile + * by setting the 'profileId' configuration in the servletConfig + * If not, the user must specify the profileID when submitting the request + * + * "ImportCert.template" to process the response. + * + * @param sc servlet configuration, read from the web.xml file + */ + public void init(ServletConfig sc) throws ServletException { + super.init(sc); + mAuthorityId = sc.getInitParameter(PROP_AUTHORITY_ID); + mProfileId = sc.getInitParameter(PROP_PROFILE_ID); + } + + private void setInputsIntoContext(HttpServletRequest request, IProfile profile, IProfileContext ctx) { + // passing inputs into context + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + ctx.set(inputName, request.getParameter(inputName)); + } + } + } + } + + } + + private void setCredentialsIntoContext(HttpServletRequest request, IProfileAuthenticator authenticator, IProfileContext ctx) { + Enumeration authIds = authenticator.getValueNames(); + + if (authIds != null) { + while (authIds.hasMoreElements()) { + String authName = (String) authIds.nextElement(); + + if (request.getParameter(authName) != null) { + ctx.set(authName, request.getParameter(authName)); + } + } + } + } + + public IAuthToken authenticate(IProfileAuthenticator authenticator, + HttpServletRequest request) throws EBaseException { + AuthCredentials credentials = new AuthCredentials(); + + // build credential + Enumeration authNames = authenticator.getValueNames(); + + if (authNames != null) { + while (authNames.hasMoreElements()) { + String authName = (String) authNames.nextElement(); + + credentials.set(authName, request.getParameter(authName)); + } + } + + credentials.set("clientHost", request.getRemoteHost()); + IAuthToken authToken = authenticator.authenticate(credentials); + + SessionContext sc = SessionContext.getContext(); + if (sc != null) { + sc.put(SessionContext.AUTH_MANAGER_ID, authenticator.getName()); + String userid = authToken.getInString(IAuthToken.USER_ID); + if (userid != null) { + sc.put(SessionContext.USER_ID, userid); + } + } + + return authToken; + } + + private void setInputsIntoRequest(HttpServletRequest request, IProfile profile, IRequest req) { + Enumeration inputIds = profile.getProfileInputIds(); + + if (inputIds != null) { + while (inputIds.hasMoreElements()) { + String inputId = (String) inputIds.nextElement(); + IProfileInput profileInput = profile.getProfileInput(inputId); + Enumeration inputNames = profileInput.getValueNames(); + + if (inputNames != null) { + while (inputNames.hasMoreElements()) { + String inputName = (String) inputNames.nextElement(); + + if (request.getParameter(inputName) != null) { + req.setExtData(inputName, request.getParameter(inputName)); + } + } + } + } + } + } + + private void setOutputIntoArgs(IProfile profile, ArgList outputlist, Locale locale, IRequest req) { + Enumeration outputIds = profile.getProfileOutputIds(); + + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId); + + Enumeration outputNames = profileOutput.getValueNames(); + + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + ArgSet outputset = new ArgSet(); + String outputName = (String) outputNames.nextElement(); + IDescriptor outputDesc = + profileOutput.getValueDescriptor(locale, outputName); + + if (outputDesc == null) + continue; + String outputSyntax = outputDesc.getSyntax(); + String outputConstraint = outputDesc.getConstraint(); + String outputValueName = outputDesc.getDescription(locale); + String outputValue = null; + + try { + outputValue = profileOutput.getValue(outputName, + locale, req); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: " + e.toString()); + } + + outputset.set(ARG_OUTPUT_ID, outputName); + outputset.set(ARG_OUTPUT_SYNTAX, outputSyntax); + outputset.set(ARG_OUTPUT_CONSTRAINT, outputConstraint); + outputset.set(ARG_OUTPUT_NAME, outputValueName); + outputset.set(ARG_OUTPUT_VAL, outputValue); + outputlist.add(outputset); + } + } + } + } + } + + /** + * Process the HTTP request + * <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("xmlOutput"); + if (v != null && v.equals("true")) + xmlOutput = true; + + IStatsSubsystem statsSub = (IStatsSubsystem)CMS.getSubsystem("stats"); + if (statsSub != null) { + statsSub.startTiming("enrollment", true /* main action */); + } + + long startTime = CMS.getCurrentDate().getTime(); + Locale locale = getLocale(request); + ArgSet args = new ArgSet(); + + if (CMS.debugOn()) { + CMS.debug("Start of Input Parameters"); + Enumeration paramNames = request.getParameterNames(); + + while (paramNames.hasMoreElements()) { + String paramName = (String) paramNames.nextElement(); + + CMS.debug("Input Parameter " + paramName + "='" + + request.getParameter(paramName) + "'"); + } + CMS.debug("End of 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; + } + + // 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("ProfileSubmitServlet: profileId " + profileId); + profile = ps.getProfile(profileId); + } catch (EProfileException e) { + CMS.debug("ProfileSubmitServlet: profile not found profileId " + + profileId + " " + 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 (!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; + } + + IProfileContext ctx = profile.createContext(); + // passing auths into context + IProfileAuthenticator authenticator = null; + + try { + authenticator = profile.getAuthenticator(); + } catch (EProfileException e) { + // authenticator not installed correctly + } + if (authenticator == null) { + CMS.debug("ProfileSubmitServlet: authenticator not found"); + } else { + CMS.debug("ProfileSubmitServlet: 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("ProfileSubmitServlet: set sslClientCertProvider"); + if (statsSub != null) { + statsSub.startTiming("profile_authentication"); + } + if (authenticator != null) { + try { + authToken = authenticate(authenticator, request); + // authentication success + } catch (EBaseException e) { + CMS.debug("ProfileSubmitServlet: authentication error " + + e.toString()); + // authentication error + if (xmlOutput) { + outputError(response, AUTH_FAILURE, CMS.getUserMessage(locale, "CMS_AUTHENTICATION_ERROR")); + } else { + args.set(ARG_ERROR_CODE, "1"); + args.set(ARG_ERROR_REASON, CMS.getUserMessage(locale, + "CMS_AUTHENTICATION_ERROR")); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("authentication"); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + return; + } + } + if (statsSub != null) { + statsSub.endTiming("profile_authentication"); + } + + if (authToken != null) { + // do profile authorization + String acl = profile.getAuthzAcl(); + if (acl != null && acl.length() > 0) { + try { + AuthzToken authzToken = authorize(mAclMethod, authToken, acl); + } catch (Exception e) { + CMS.debug("ProfileSubmitServlet authorize: "+e.toString()); + if (xmlOutput) + outputError(response, CMS.getUserMessage(locale, + "CMS_AUTHORIZATION_ERROR")); + 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: 1 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 + setInputsIntoRequest(request, profile, reqs[k]); + + // serial auth token into request + if (authToken != null) { + Enumeration tokenNames = authToken.getElements(); + while (tokenNames.hasMoreElements()) { + String tokenName = (String) tokenNames.nextElement(); + String[] tokenVals = authToken.getInStringArray(tokenName); + if (tokenVals != null) { + for (int i = 0; i < tokenVals.length; i++) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + + tokenName + "[" + i + "]", tokenVals[i]); + } + } else { + String tokenVal = authToken.getInString(tokenName); + if (tokenVal != null) { + reqs[k].setExtData(ARG_AUTH_TOKEN + "." + tokenName, + tokenVal); + // if RA agent, auto assign the request + if (tokenName.equals("uid")) + uid = tokenVal; + if (tokenName.equals("group") && + tokenVal.equals("Registration Manager Agents")) { + fromRA = true; + } + } + } + } + } + + if (fromRA) { + CMS.debug("ProfileSubmitServlet: request from RA: "+ uid); + reqs[k].setExtData(ARG_REQUEST_OWNER, uid); + } + + // put profile framework parameters into the request + reqs[k].setExtData(ARG_PROFILE, "true"); + reqs[k].setExtData(ARG_PROFILE_ID, profileId); + 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, CMS.getUserMessage("CMS_PROFILE_NO_POLICY_SET_FOUND")); + } 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, 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("ProfileSubmitServlet: populate " + e.toString()); + // throw new IOException("Profile " + profileId + + // " cannot populate"); + 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; + } + } + 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 + /////////////////////////////////////////////// + for (int k = 0; k < reqs.length; k++) { + try { + // reset the "auditRequesterID" + auditRequesterID = auditRequesterID(reqs[k]); + + + // print request debug + if (reqs[k] != null) { + Enumeration reqKeys = reqs[k].getExtDataKeys(); + while (reqKeys.hasMoreElements()) { + String reqKey = (String)reqKeys.nextElement(); + String reqVal = reqs[k].getExtDataInString(reqKey); + if (reqVal != null) { + CMS.debug("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 { + 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) { + outputError(response, errorReason); + } else { + ArgList requestlist = new ArgList(); + + for (int k = 0; k < reqs.length; k++) { + ArgSet requestset = new ArgSet(); + + requestset.set(ARG_REQUEST_ID, + reqs[k].getRequestId().toString()); + requestlist.add(requestset); + } + args.set(ARG_REQUEST_LIST, requestlist); + args.set(ARG_ERROR_CODE, errorCode); + args.set(ARG_ERROR_REASON, errorReason); + outputTemplate(request, response, args); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + return; + } + + /////////////////////////////////////////////// + // output output list + /////////////////////////////////////////////// + if (xmlOutput) { + xmlOutput(response, profile, locale, reqs); + } else { + ArgList outputlist = new ArgList(); + for (int k = 0; k < reqs.length; k++) { + + setOutputIntoArgs(profile, outputlist, locale, reqs[k]); + args.set(ARG_OUTPUT_LIST, outputlist); + } + + CMS.debug("ProfileSubmitServlet: done serving"); + + ArgList requestlist = new ArgList(); + + for (int k = 0; k < reqs.length; k++) { + ArgSet requestset = new ArgSet(); + + requestset.set(ARG_REQUEST_ID, + reqs[k].getRequestId().toString()); + requestlist.add(requestset); + } + args.set(ARG_REQUEST_LIST, requestlist); + args.set(ARG_ERROR_CODE, "0"); + args.set(ARG_ERROR_REASON, ""); + + outputTemplate(request, response, args); + } + } catch (EBaseException eAudit1) { + // store a message in the signed audit log file + // (automated cert request processed - "rejected") + auditMessage = CMS.getLogMessage( + LOGGING_SIGNED_AUDIT_CERT_REQUEST_PROCESSED, + auditSubjectID, + ILogger.FAILURE, + auditRequesterID, + ILogger.SIGNED_AUDIT_REJECTION, + SIGNED_AUDIT_AUTOMATED_REJECTION_REASON[0]); + + audit(auditMessage); + + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + throw eAudit1; + } finally { + context.releaseContext(); + } + if (statsSub != null) { + statsSub.endTiming("enrollment"); + } + } + + private void xmlOutput(HttpServletResponse httpResp, IProfile profile, Locale locale, IRequest[] reqs) { + try { + XMLObject xmlObj = null; + xmlObj = new XMLObject(); + + Node root = xmlObj.createRoot("XMLResponse"); + xmlObj.addItemToContainer(root, "Status", SUCCESS); + Node n = xmlObj.createContainer(root, "Requests"); + CMS.debug("ProfileSubmitServlet xmlOutput: req len = " +reqs.length); + + for (int i=0; i<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 outputIds = profile.getProfileOutputIds(); + if (outputIds != null) { + while (outputIds.hasMoreElements()) { + String outputId = (String) outputIds.nextElement(); + IProfileOutput profileOutput = profile.getProfileOutput(outputId); + Enumeration outputNames = profileOutput.getValueNames(); + if (outputNames != null) { + while (outputNames.hasMoreElements()) { + String outputName = (String) 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 = com.netscape.osutil.OSUtil.BtoA(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (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/pki/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java b/pki/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java new file mode 100644 index 000000000..c548d0db9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/profile/SSLClientCertProvider.java @@ -0,0 +1,40 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.profile; + +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import java.security.cert.*; +import com.netscape.certsrv.authentication.*; + +public class SSLClientCertProvider implements ISSLClientCertProvider { + private HttpServletRequest mRequest = null; + + public SSLClientCertProvider(HttpServletRequest request) { + mRequest = request; + } + + public X509Certificate[] getClientCertificateChain() { + X509Certificate[] allCerts = (X509Certificate[]) + mRequest.getAttribute("javax.servlet.request.X509Certificate"); + + return allCerts; + } +} + diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java b/pki/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java new file mode 100644 index 000000000..5b19f72d0 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/CertReqParser.java @@ -0,0 +1,893 @@ +// --- 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 com.netscape.cms.servlet.common.*; + +import java.io.*; +import java.util.*; +import java.math.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.lang.reflect.Array; +import netscape.security.x509.*; +import netscape.security.extensions.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.apps.*; + +import com.netscape.certsrv.request.*; + + +/** + * Output a 'pretty print' of a certificate request + * + * @version $Revision: 14711 $, $Date: 2007-05-09 17:13:13 -0700 (Wed, 09 May 2007) $ + */ +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 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.equals(IRequest.HTTP_PARAMS)) { + Hashtable http_params = req.getExtDataInHashtable(name); + // show certType specially + String certType = (String) 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 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.equals(IRequest.HTTP_HEADERS)) { + Hashtable http_hdrs = req.getExtDataInHashtable(name); + Enumeration elms = http_hdrs.keys(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_HEADERS + 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_hdrs.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all auth token stored in request. + else if (name.equals(IRequest.AUTH_TOKEN)) { + IAuthToken auth_token = req.getExtDataInAuthToken(name); + Enumeration 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(); + 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; + + 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.equals(IRequest.REQUESTOR_PHONE) + || name.equals(IRequest.REQUESTOR_EMAIL) + || name.equals(IRequest.REQUESTOR_COMMENTS) + || name.equals(IRequest.RESULT) + || name.equals(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE) + ) { + arg.addStringValue(name, req.getExtDataInString(name)); + } + + if (name.equals(IRequest.REQUESTOR_NAME)) { + String requestorName = req.getExtDataInString(name); + + requestorName = requestorName.trim(); + if (requestorName.length() > 0) { + arg.addStringValue(name, requestorName); + } + } + + if (name.equals(IRequest.ERRORS)) { + Vector 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.equals(IRequest.ERROR)) { + arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name)); + } + + if (name.equals(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 exts = extensions.getElements(); + + while (exts.hasMoreElements()) { + Extension ext = (Extension) 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.equals(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.equals(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.equals(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.equals(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.equals(IRequest.FINGERPRINTS) && mDetails) { + Hashtable fingerprints = + req.getExtDataInHashtable(IRequest.FINGERPRINTS); + + if (fingerprints != null) { + String namesAndHashes = null; + Enumeration enumFingerprints = fingerprints.keys(); + + while (enumFingerprints.hasMoreElements()) { + String hashname = (String) enumFingerprints.nextElement(); + String hashvalue = (String) 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 (Enumeration n = ((Vector) 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 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.equals(IRequest.HTTP_PARAMS)) { + Hashtable http_params = req.getExtDataInHashtable(name); + // show certType specially + String certType = (String) 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 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.equals(IRequest.HTTP_HEADERS)) { + Hashtable http_hdrs = req.getExtDataInHashtable(name); + Enumeration elms = http_hdrs.keys(); + int counter = 0; + + while (elms.hasMoreElements()) { + String parami = + IRequest.HTTP_HEADERS + 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_hdrs.get(n).toString()) + "\""; + + arg.set(parami, new RawJS(rawJS)); + } + } // show all auth token stored in request. + else if (name.equals(IRequest.AUTH_TOKEN)) { + IAuthToken auth_token = req.getExtDataInAuthToken(name); + Enumeration 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.equals(IRequest.REQUESTOR_PHONE) + || name.equals(IRequest.REQUESTOR_EMAIL) + || name.equals(IRequest.REQUESTOR_COMMENTS) + || name.equals(IRequest.RESULT) + || name.equals(IRequest.REQUEST_TRUSTEDMGR_PRIVILEGE) + ) { + arg.addStringValue(name, req.getExtDataInString(name)); + } + + if (name.equals(IRequest.REQUESTOR_NAME)) { + String requestorName = req.getExtDataInString(name); + + requestorName = requestorName.trim(); + if (requestorName.length() > 0) { + arg.addStringValue(name, requestorName); + } + } + + if (name.equals(IRequest.ERRORS)) { + Vector 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.equals(IRequest.ERROR)) { + arg.addStringValue(IRequest.ERRORS, req.getExtDataInString(name)); + } + + if (name.equals(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.equals(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.equals(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.equals(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/pki/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java b/pki/base/common/src/com/netscape/cms/servlet/request/CheckRequest.java new file mode 100644 index 000000000..e6f292d01 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/CheckRequest.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.request; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; + +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; + +import java.security.*; +import java.security.cert.*; +import netscape.security.pkcs.*; + +import org.mozilla.jss.CryptoManager; +import org.mozilla.jss.crypto.SignatureAlgorithm; +import org.mozilla.jss.crypto.DigestAlgorithm; +import org.mozilla.jss.pkix.cmc.*; +import org.mozilla.jss.pkix.cms.*; +import org.mozilla.jss.pkix.cert.*; +import org.mozilla.jss.pkix.primitive.*; +import org.mozilla.jss.asn1.*; + + +/** + * Check the status of a certificate request + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class CheckRequest extends CMSServlet { + // 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, rNonces = 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)) { + rNonces = taggedAttr.getValues(); + } 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 { + Integer.parseInt(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/pki/base/common/src/com/netscape/cms/servlet/request/IReqParser.java b/pki/base/common/src/com/netscape/cms/servlet/request/IReqParser.java new file mode 100644 index 000000000..346cc8ebb --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/IReqParser.java @@ -0,0 +1,55 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + +import com.netscape.certsrv.request.*; +import com.netscape.cms.servlet.*; + + +/** + * An interface representing a request parser which + * converts Java request object into name value + * pairs and vice versa. + * <P> + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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/pki/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java b/pki/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.java new file mode 100644 index 000000000..4c633cd0c --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/KeyReqParser.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 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; + +import java.math.BigInteger; +import java.util.Locale; + + +/** + * Output a 'pretty print' of a Key Archival request + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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()); + } else { + System.out.println("Bad Request " + type); + // invalid request + } + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java b/pki/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java new file mode 100644 index 000000000..7af438402 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/ProcessCertReq.java @@ -0,0 +1,1912 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.extensions.*; +import netscape.security.x509.*; +import netscape.security.util.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.authority.*; +import com.netscape.cms.servlet.cert.*; + +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.logging.*; + + +/** + * Agent operations on Certificate requests. This servlet is used + * by an Agent to approve, reject, reassign, or change a certificate + * request. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProcessCertReq extends CMSServlet { + + 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; + int seqNum = -1; + 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, errorForm = 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 = Integer.parseInt(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 > -1) { + r = mQueue.findRequest(new RequestId( + Integer.toString(seqNum))); + } + + if(seqNum > -1 && 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", String.valueOf(seqNum))); + error = new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + String.valueOf(seqNum))); + } + } 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 { + String output = form.getOutput(argSet); + 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, + int 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( + Integer.toString(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 extsToBeAdded = new Vector(); + + byte[] b = (byte[]) (com.netscape.osutil.OSUtil.AtoB(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) { + Enumeration extraparams = req.getParameterNames(); + int l = IRequest.AGENT_PARAMS.length() + 1; + int ap_counter = 0; + Hashtable agentparamsargblock = new Hashtable(); + + if (extraparams != null) { + while (extraparams.hasMoreElements()) { + String s = (String) 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 + Object grantError = null; + + try { + int res = grant_privileges( + cmsReq, r, issuedCerts, header); + + if (res != 0) { + header.addStringValue(GRANT_ERROR, "SUCCESS"); + grantError = "SUCCESS"; + } + } catch (EBaseException e) { + header.addStringValue(GRANT_ERROR, e.toString()); + grantError = e; + } + + // 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.addIntegerValue("seqNum", seqNum); + 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 = com.netscape.osutil.OSUtil.BtoA(rawData).trim(); + + // extract all line separators from the "base64Data" + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < base64Data.length(); i++) { + if (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/pki/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java b/pki/base/common/src/com/netscape/cms/servlet/request/ProcessReq.java new file mode 100644 index 000000000..d3cb684ff --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/ProcessReq.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.request; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.ra.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.dbs.keydb.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.logging.*; + + +/** + * Display Generic Request detail to the user. + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class ProcessReq extends CMSServlet { + + 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 { + int seqNum = -1; + + 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, errorForm = 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 = Integer.parseInt(req.getParameter(SEQNUM)); + } + doAssign = req.getParameter(DO_ASSIGN); + + if (seqNum > -1) { + // 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 { + String output = form.getOutput(argSet); + 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, + int seqNum, HttpServletRequest req, + HttpServletResponse resp, + String doAssign, Locale locale) + throws EBaseException { + + header.addIntegerValue("seqNum", seqNum); + + IRequest r = + mQueue.findRequest(new RequestId(Integer.toString(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); + throw new ECMSGWException( + CMS.getUserMessage("CMS_GW_INVALID_REQUEST_ID", + String.valueOf(seqNum))); + } + + return; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/QueryReq.java b/pki/base/common/src/com/netscape/cms/servlet/request/QueryReq.java new file mode 100644 index 000000000..5b4a3b059 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/QueryReq.java @@ -0,0 +1,533 @@ +// --- 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 com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.logging.*; + + +/** + * Show paged list of requests matching search criteria + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class QueryReq extends CMSServlet { + // 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_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; + + 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; + + 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_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(); + } + + + int top=0, bottom=0; + + 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"; + + top = Integer.parseInt(top_s); + bottom = Integer.parseInt(bottom_s); + + } catch (NumberFormatException e) { + + } + + // avoid NumberFormatException to the user interface + int maxCount = 10; + try { + maxCount = Integer.parseInt(req.getParameter(IN_MAXCOUNT)); + } catch (Exception e) { + } + + 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; + } + + private static String makeRequestStatusEq(RequestStatus s) { + return "(" + "requestState" + "=" + s + ")"; + } + + private static String makeRequestIdCmp(String op, int bound) { + return "(requestId" + op + bound + ")"; + } + + /** + * 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, int top, int bottom) + { + CMSTemplateParams ctp = null; + if (direction.equals("previous")) { + ctp = doSearch(l, filter, -count, top-1); + } else if (direction.equals("next")) { + ctp = doSearch(l,filter, count, bottom+1); + } else if (direction.equals("begin")) { + ctp = doSearch(l,filter, count, 0); + } else { // if 'direction is 'end', default here + ctp = doSearch(l,filter, -count, -1); + } + 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, + int 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 == -1) { + marker = 0; // I think this is inconsequential + jumptoend = true; // override to '99' during search + } + + RequestId id = new RequestId(Integer.toString(marker)); + IRequestVirtualList list = mQueue.getPagedRequestsByFilter( + id, + jumptoend, + filter, + count+1, + "requestId"); + + int totalCount = list.getSize() - list.getCurrentIndex(); + header.addIntegerValue(OUT_TOTALCOUNT, totalCount); + header.addIntegerValue(OUT_CURRENTCOUNT, list.getSize()); + + int numEntries = list.getSize() - list.getCurrentIndex(); + + Vector v = fetchRecords(list,Math.abs(count)); + v = normalizeOrder(v); + trim(v,id); + + + int currentCount = 0; + int curNum = 0; + int firstNum = -1; + Enumeration requests = v.elements(); + + while (requests.hasMoreElements()) { + IRequest request = null; + try { + request = (IRequest) 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 = Integer.parseInt( + request.getRequestId().toString()); + + if (firstNum == -1) { + 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.addIntegerValue(OUT_FIRST_ENTRY_ON_PAGE, firstNum); + header.addIntegerValue(OUT_LAST_ENTRY_ON_PAGE, curNum); + + } 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 v, RequestId marker) { + int i = v.size()-1; + if (((IRequest)v.elementAt(i)).getRequestId().equals(marker)) { + 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 fetchRecords(IRequestVirtualList list, int maxCount) { + + Vector v = new Vector(); + 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 normalizeOrder(Vector list) { + + int firstrequestnum = Integer.parseInt(((IRequest) list.elementAt(0)) + .getRequestId().toString()); + int lastrequestnum = Integer.parseInt(((IRequest) list.elementAt(list + .size() - 1)).getRequestId().toString()); + boolean reverse = false; + if (firstrequestnum > lastrequestnum) { + reverse = true; // if the order is backwards, place items at the beginning + } + Vector v = new Vector(); + int count = list.size(); + for (int i = 0; i < count; i++) { + Object request = list.elementAt(i); + if (request != null) { + if (reverse) + v.add(0, request); + else + v.add(request); + } + } + + return v; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/request/ReqParser.java b/pki/base/common/src/com/netscape/cms/servlet/request/ReqParser.java new file mode 100644 index 000000000..d4ca29da3 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/ReqParser.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) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.servlet.request; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.dbs.*; + +import com.netscape.certsrv.request.*; +import com.netscape.cms.servlet.*; + + +/** + * A class representing a request parser. + * <P> + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +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.addLongValue("seqNum", + Long.parseLong(req.getRequestId().toString())); + 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/pki/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java b/pki/base/common/src/com/netscape/cms/servlet/request/SearchReqs.java new file mode 100644 index 000000000..38fb050c9 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/request/SearchReqs.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.request; + + +import com.netscape.cms.servlet.common.*; +import com.netscape.cms.servlet.base.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import netscape.security.provider.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.authority.*; +import com.netscape.cms.servlet.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.request.*; + + +/** + * XXX Search for certificates matching complex query filter + * + * @version $Revision: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class SearchReqs extends CMSServlet { + + 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 IRequestQueue mQueue = null; + private IReqParser mParser = null; + private String mFormPath = null; + private int mMaxReturns = 100; + + /** + * 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, 100); + } catch (EBaseException e) { + // do nothing + } + } + } + if (mAuthority instanceof ICertificateAuthority) { + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + mQueue = ca.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; + } + + /** + * 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]; + + 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 = ""; + 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+")"; + } + String newfilter = "(&"+requestowner_filter+filter.substring(2); + // xxx the filter includes serial number range??? + int mr = (maxResults > 0) ? maxResults : mMaxReturns; + IRequestList list = (timeLimit > 0) ? + mQueue.listRequestsByFilter(newfilter, mr, timeLimit) : + mQueue.listRequestsByFilter(newfilter, mr); + + 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/pki/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java b/pki/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.java new file mode 100644 index 000000000..fa0d7a683 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/tks/TokenServlet.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.tks; + +import org.mozilla.jss.crypto.*; +import org.mozilla.jss.*; +import org.mozilla.jss.pkcs11.*; + +import sun.misc.*; +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import javax.servlet.*; +import javax.servlet.http.*; +import netscape.security.x509.*; +import java.net.URLEncoder; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.password.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.security.*; +import com.netscape.certsrv.usrgrp.*; +import com.netscape.certsrv.apps.CMS; +import com.netscape.cms.servlet.base.*; +import com.netscape.cms.servlet.common.*; +import com.netscape.cmsutil.util.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.authorization.*; +import com.netscape.certsrv.tks.*; +import com.netscape.symkey.*; + + + +/** + * 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: 14561 $, $Date: 2007-05-01 10:28:56 -0700 (Tue, 01 May 2007) $ + */ +public class TokenServlet extends CMSServlet { + protected static final String PROP_ENABLED = "enabled"; + + 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(":"); + + /** + * 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 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; + SymmetricKey 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; + + 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) { + } + + String rcard_challenge = req.getParameter("card_challenge"); + String rhost_challenge = req.getParameter("host_challenge"); + String rKeyInfo = req.getParameter("KeyInfo"); + String rCUID = req.getParameter("CUID"); + String rcard_cryptogram = req.getParameter("card_cryptogram"); + if ((rCUID == null) || (rCUID.equals(""))) { + CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: CUID"); + missingParam = true; + } + + if ((rcard_challenge == null) || (rcard_challenge.equals(""))) { + CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: card challenge"); + missingParam = true; + } + + if ((rhost_challenge == null) || (rhost_challenge.equals(""))) { + CMS.debug("TokenServlet: ComputeSessionKey(): missing request parameter: host challenge"); + missingParam = true; + } + + if ((rKeyInfo == null) || (rKeyInfo.equals(""))) { + 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) { + CMS.debug("TokenServlet: Invalid CUID length"); + missingParam = true; + } + xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo); + if (xkeyInfo == null || xkeyInfo.length != 2) { + 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) { + 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) { + CMS.debug("TokenServlet: Invalid host challenge length"); + missingParam = true; + } + } + + 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); + + 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); + + 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); + 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"); + desKey = SessionKey.GenerateSymkey("internal"); + } 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.getKeyData()); + /* + 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.getKeyData()); + /* + 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("Internal Key Storage Token"); + } else { + token = CryptoManager.getInstance().getTokenByName(selectedToken); + } + PublicKey pubKey = drmTransCert.getPublicKey(); + String pubKeyAlgo = pubKey.getAlgorithm(); + CMS.debug("Transport Cert Key Algorithm: " + pubKeyAlgo); + KeyWrapper rsaWrap = null; + if (pubKeyAlgo.equals("EC")) { + byte iv[] = {0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1}; + IVParameterSpec IV = new IVParameterSpec(iv); + rsaWrap = token.getKeyWrapper(KeyWrapAlgorithm.AES_CBC); + rsaWrap.initWrap(pubKey, IV); + } else { + rsaWrap = token.getKeyWrapper(KeyWrapAlgorithm.RSA); + rsaWrap.initWrap(pubKey, null); + } + drm_trans_wrapped_desKey = rsaWrap.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); + + 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); + + 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")) + 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()); + } + } + + private void processDiversifyKey(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + byte[] KeySetData,KeysValues,CUID,xCUID; + byte[] xkeyInfo,xnewkeyInfo; + boolean missingParam = false; + + 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 keySet = req.getParameter("keySet"); + if (keySet == null || keySet.equals("")) { + keySet = "defKeySet"; + } + CMS.debug("keySet selected: " + keySet); + + if ((rCUID == null) || (rCUID.equals(""))) { + CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: CUID"); + missingParam = true; + } + if ((rnewKeyInfo == null) || (rnewKeyInfo.equals(""))) { + CMS.debug("TokenServlet: processDiversifyKey(): missing request parameter: newKeyInfo"); + missingParam = true; + } + if ((oldMasterKeyName == null) || (oldMasterKeyName.equals(""))){ + 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) { + CMS.debug("TokenServlet: Invalid key info length"); + missingParam = true; + } + xnewkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(newMasterKeyName); + if (xnewkeyInfo == null || xnewkeyInfo.length != 2) { + 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; + String outputString = null; + if (!missingParam) { + xCUID = com.netscape.cmsutil.util.Utils.SpecialDecode(rCUID); + if (xCUID == null || xCUID.length != 10) { + 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); + + 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"); + + if (KeySetData != null) { + outputString = new String(KeySetData); + } + } // ! missingParam + + //CMS.debug("TokenServlet:processDiversifyKey " +outputString); + //String value="keySetData=%00" if the KeySetData=byte[0]=0; + + String value = ""; + 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) { + value = "status=3"; + } else + value = "status=1"; + + 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()); + } + } + + private void processEncryptData(HttpServletRequest req, + HttpServletResponse resp) throws EBaseException { + byte[] data,keyInfo, CUID, xCUID, encryptedData, xkeyInfo; + boolean missingParam = false; + + 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"; + } + CMS.debug("keySet selected: " + keySet); + + if ((rdata == null) || (rdata.equals(""))) { + CMS.debug("TokenServlet: processEncryptData(): missing request parameter: data"); + missingParam = true; + } + + if ((rCUID == null) || (rCUID.equals(""))) { + + CMS.debug("TokenServlet: processEncryptData(): missing request parameter: CUID"); + missingParam = true; + } + if ((rKeyInfo == null) || (rKeyInfo.equals(""))) { + 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) { + CMS.debug("TokenServlet: Invalid CUID length"); + throw new EBaseException("Invalid CUID length"); + } + xkeyInfo = com.netscape.cmsutil.util.Utils.SpecialDecode(rKeyInfo); + if (xkeyInfo == null || xkeyInfo.length != 2) { + CMS.debug("TokenServlet: Invalid key info length"); + throw new EBaseException("Invalid key info length"); + } + } + + String useSoftToken_s = CMS.getConfigStore().getString("tks.useSoftToken","true"); + if (!useSoftToken_s.equalsIgnoreCase("true")) + useSoftToken_s = "false"; + + if (!missingParam) { + 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); + String selectedToken = null; + String keyNickName = 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); + + 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 = ""; + if (encryptedData != null && encryptedData.length > 0) { + String outputString = new String(encryptedData); + value = "status=0&"+"encryptedData=" + + com.netscape.cmsutil.util.Utils.SpecialEncode(encryptedData); + } else if (missingParam) { + value = "status=3"; + } else + value = "status=1"; + + 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()); + } + } + + /* + * 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 + */ + + 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) { + } + + 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); + } + } + + /** + * Serves HTTP admin request. + * + * @param req HTTP request + * @param resp HTTP response + */ + public void service(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + String scope = req.getParameter(Constants.OP_SCOPE); + String op = req.getParameter(Constants.OP_TYPE); + + super.service(req, resp); + } + + /** + * Parses uid0=pwd0,uid1=pwd1,... into AgentCredential. + * + * @param s credential string + * @return a list of credentials + */ + private Credential[] parseCredentialStr(String s) { + StringTokenizer st = new StringTokenizer(s, ","); + Vector v = new Vector(); + + while (st.hasMoreTokens()) { + String a = st.nextToken(); + StringTokenizer st0 = new StringTokenizer(a, "="); + + v.addElement(new Credential(st0.nextToken(), + st0.nextToken())); + } + Credential ac[] = new Credential[v.size()]; + + v.copyInto(ac); + return ac; + } +} diff --git a/pki/base/common/src/com/netscape/cms/servlet/wizard/IWizardPanel.java b/pki/base/common/src/com/netscape/cms/servlet/wizard/IWizardPanel.java new file mode 100644 index 000000000..199a4f4d1 --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/wizard/IWizardPanel.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.wizard; + +import org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.*; +import javax.servlet.http.*; + +import java.io.*; +import com.netscape.certsrv.property.*; + +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/pki/base/common/src/com/netscape/cms/servlet/wizard/WizardServlet.java b/pki/base/common/src/com/netscape/cms/servlet/wizard/WizardServlet.java new file mode 100644 index 000000000..63119e82e --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/servlet/wizard/WizardServlet.java @@ -0,0 +1,478 @@ +// --- 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 org.apache.velocity.Template; +import org.apache.velocity.servlet.VelocityServlet; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.context.Context; +import javax.servlet.http.*; +import javax.servlet.*; + +import java.io.*; +import java.util.*; + +import com.netscape.cmsutil.crypto.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cms.servlet.csadmin.*; + +/** + * 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 String name = null; + private Vector mPanels = new Vector(); + + 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 e = mPanels.elements(); + Vector panels = new Vector(); + 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 = (IWizardPanel)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 = (IWizardPanel)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 = (IWizardPanel)mPanels.elementAt(p); + return wp.getId(); + } + + public IWizardPanel getPreviousPanel(int p) + { + CMS.debug("getPreviousPanel input p=" + p); + IWizardPanel backpanel = (IWizardPanel)mPanels.elementAt(p-1); + if (backpanel.isSubPanel()) { + backpanel = (IWizardPanel)mPanels.elementAt(p-1-1); + } + while (backpanel.shouldSkip()) { + backpanel = (IWizardPanel) + 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 = (IWizardPanel)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 = (IWizardPanel)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:serice() uri = " + httpReq.getRequestURI()); + Enumeration paramNames = httpReq.getParameterNames(); + while (paramNames.hasMoreElements()) { + String pn = (String)paramNames.nextElement(); + if (pn.startsWith("__")) { + CMS.debug("CMSServlet::service() param name='" + pn + "' value='(sensitive)'" ); + } else { + CMS.debug("CMSServlet::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; + } +} |