diff options
author | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-24 02:27:47 -0500 |
---|---|---|
committer | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-26 11:43:54 -0500 |
commit | 621d9e5c413e561293d7484b93882d985b3fe15f (patch) | |
tree | 638f3d75761c121d9a8fb50b52a12a6686c5ac5c /base/common/src/com/netscape/cmscore/policy | |
parent | 40d3643b8d91886bf210aa27f711731c81a11e49 (diff) | |
download | pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.gz pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.xz pki-621d9e5c413e561293d7484b93882d985b3fe15f.zip |
Removed unnecessary pki folder.
Previously the source code was located inside a pki folder.
This folder was created during svn migration and is no longer
needed. This folder has now been removed and the contents have
been moved up one level.
Ticket #131
Diffstat (limited to 'base/common/src/com/netscape/cmscore/policy')
8 files changed, 3491 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cmscore/policy/AndExpression.java b/base/common/src/com/netscape/cmscore/policy/AndExpression.java new file mode 100644 index 000000000..459660f1e --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/AndExpression.java @@ -0,0 +1,60 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.policy; + +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IExpression; +import com.netscape.certsrv.request.IRequest; + +/** + * This class represents an expression of the form + * <var1 op val1 AND var2 op va2>. + * + * Expressions are used as predicates for policy selection. + * + * @deprecated + * @author kanda + * @version $Revision$, $Date$ + */ +public class AndExpression implements IExpression { + private IExpression mExp1; + private IExpression mExp2; + + public AndExpression(IExpression exp1, IExpression exp2) { + mExp1 = exp1; + mExp2 = exp2; + } + + public boolean evaluate(IRequest req) + throws EPolicyException { + // If an expression is missing we assume applicability. + if (mExp1 == null && mExp2 == null) + return true; + else if (mExp1 != null && mExp2 != null) + return mExp1.evaluate(req) && mExp2.evaluate(req); + else if (mExp1 == null) + return mExp2.evaluate(req); + else + // (if mExp2 == null) + return mExp1.evaluate(req); + } + + public String toString() { + return mExp1.toString() + " AND " + mExp2.toString(); + } +} diff --git a/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java b/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java new file mode 100644 index 000000000..7c7162d0c --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java @@ -0,0 +1,694 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.policy; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.Enumeration; +import java.util.StringTokenizer; +import java.util.Vector; + +import netscape.security.util.DerValue; +import netscape.security.util.ObjectIdentifier; +import netscape.security.x509.DNSName; +import netscape.security.x509.EDIPartyName; +import netscape.security.x509.GeneralName; +import netscape.security.x509.GeneralNameInterface; +import netscape.security.x509.GeneralNames; +import netscape.security.x509.IPAddressName; +import netscape.security.x509.InvalidIPAddressException; +import netscape.security.x509.OIDName; +import netscape.security.x509.RFC822Name; +import netscape.security.x509.URIName; +import netscape.security.x509.X500Name; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.EPropertyNotFound; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.policy.IGeneralNameAsConstraintsConfig; +import com.netscape.certsrv.policy.IGeneralNameConfig; +import com.netscape.certsrv.policy.IGeneralNameUtil; +import com.netscape.certsrv.policy.IGeneralNamesAsConstraintsConfig; +import com.netscape.certsrv.policy.IGeneralNamesConfig; +import com.netscape.certsrv.policy.ISubjAltNameConfig; +import com.netscape.cmscore.util.Debug; +import com.netscape.cmsutil.util.Utils; + +/** + * Class that can be used to form general names from configuration file. + * Used by policies and extension commands. + * @deprecated + */ +public class GeneralNameUtil implements IGeneralNameUtil { + + private static final String DOT = "."; + + /** + * GeneralName can be used in the context of Constraints. Examples + * are NameConstraints, CertificateScopeOfUse extensions. In such + * cases, IPAddress may contain netmask component. + */ + static public GeneralName + form_GeneralNameAsConstraints(String generalNameChoice, String value) + throws EBaseException { + try { + if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_IPADDRESS)) { + StringTokenizer st = new StringTokenizer(value, ","); + String ip = st.nextToken(); + String netmask = null; + + if (st.hasMoreTokens()) { + netmask = st.nextToken(); + } + return new GeneralName(new IPAddressName(ip, netmask)); + } else { + return form_GeneralName(generalNameChoice, value); + } + } catch (InvalidIPAddressException e) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_IP_ADDR", value)); + } + } + + /** + * Form a General Name from a General Name choice and value. + * The General Name choice must be one of the General Name Choice Strings + * defined in this class. + * + * @param generalNameChoice General Name choice. Must be one of the General + * Name choices defined in this class. + * @param value String value of the general name to form. + */ + static public GeneralName + form_GeneralName(String generalNameChoice, String value) + throws EBaseException { + GeneralNameInterface generalNameI = null; + DerValue derVal = null; + GeneralName generalName = null; + + try { + if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_OTHERNAME)) { + byte[] val = Utils.base64decode(value); + + derVal = new DerValue(new ByteArrayInputStream(val)); + Debug.trace("otherName formed"); + } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_RFC822NAME)) { + generalNameI = new RFC822Name(value); + Debug.trace("rfc822Name formed "); + } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DNSNAME)) { + generalNameI = new DNSName(value); + Debug.trace("dnsName formed"); + }/** + * not supported -- no sun class + * else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_X400ADDRESS)) { + * } + **/ + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DIRECTORYNAME)) { + generalNameI = new X500Name(value); + Debug.trace("X500Name formed"); + } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_EDIPARTYNAME)) { + generalNameI = new EDIPartyName(value); + Debug.trace("ediPartyName formed"); + } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_URL)) { + generalNameI = new URIName(value); + Debug.trace("url formed"); + } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_IPADDRESS)) { + generalNameI = new IPAddressName(value); + Debug.trace("ipaddress formed"); + } else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_REGISTEREDID)) { + ObjectIdentifier oid; + + try { + oid = new ObjectIdentifier(value); + } catch (Exception e) { + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_VALUE_FOR_TYPE", + generalNameChoice, + "value must be a valid OID in the form n.n.n.n")); + } + generalNameI = new OIDName(oid); + Debug.trace("oidname formed"); + } else { + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + new String[] { + PROP_GENNAME_CHOICE, + "value must be one of: " + + GENNAME_CHOICE_OTHERNAME + ", " + + GENNAME_CHOICE_RFC822NAME + ", " + + GENNAME_CHOICE_DNSNAME + ", " + + + /* GENNAME_CHOICE_X400ADDRESS +", "+ */ + GENNAME_CHOICE_DIRECTORYNAME + ", " + + GENNAME_CHOICE_EDIPARTYNAME + ", " + + GENNAME_CHOICE_URL + ", " + + GENNAME_CHOICE_IPADDRESS + ", or " + + GENNAME_CHOICE_REGISTEREDID + "." + } + )); + } + } catch (IOException e) { + Debug.printStackTrace(e); + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_VALUE_FOR_TYPE", + generalNameChoice, e.toString())); + } catch (InvalidIPAddressException e) { + Debug.printStackTrace(e); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_IP_ADDR", value)); + } catch (RuntimeException e) { + Debug.printStackTrace(e); + throw e; + } + + try { + if (generalNameI != null) + generalName = new GeneralName(generalNameI); + else + generalName = new GeneralName(derVal); + Debug.trace("general name formed"); + return generalName; + } catch (IOException e) { + Debug.printStackTrace(e); + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", "Could not form GeneralName. Error: " + e)); + } + } + + /** + * Checks if given string is a valid General Name choice and returns + * the actual string that can be passed into form_GeneralName(). + * + * @param generalNameChoice a General Name choice string. + * @return one of General Name choices defined in this class that can be + * passed into form_GeneralName(). + */ + static public String check_GeneralNameChoice(String generalNameChoice) + throws EBaseException { + String theGeneralNameChoice = null; + + if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_OTHERNAME)) + theGeneralNameChoice = GENNAME_CHOICE_OTHERNAME; + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_RFC822NAME)) + theGeneralNameChoice = GENNAME_CHOICE_RFC822NAME; + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DNSNAME)) + theGeneralNameChoice = GENNAME_CHOICE_DNSNAME; + + /* X400Address not supported. + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_X400ADDRESS)) + theGeneralNameChoice = GENNAME_CHOICE_X400ADDRESS; + */ + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_DIRECTORYNAME)) + theGeneralNameChoice = GENNAME_CHOICE_DIRECTORYNAME; + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_EDIPARTYNAME)) + theGeneralNameChoice = GENNAME_CHOICE_EDIPARTYNAME; + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_URL)) + theGeneralNameChoice = GENNAME_CHOICE_URL; + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_IPADDRESS)) + theGeneralNameChoice = GENNAME_CHOICE_IPADDRESS; + else if (generalNameChoice.equalsIgnoreCase(GENNAME_CHOICE_REGISTEREDID)) + theGeneralNameChoice = GENNAME_CHOICE_REGISTEREDID; + else { + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + new String[] { + PROP_GENNAME_CHOICE + "=" + generalNameChoice, + "value must be one of: " + + GENNAME_CHOICE_OTHERNAME + ", " + + GENNAME_CHOICE_RFC822NAME + ", " + + GENNAME_CHOICE_DNSNAME + ", " + + + /* GENNAME_CHOICE_X400ADDRESS +", "+ */ + GENNAME_CHOICE_DIRECTORYNAME + ", " + + GENNAME_CHOICE_EDIPARTYNAME + ", " + + GENNAME_CHOICE_URL + ", " + + GENNAME_CHOICE_IPADDRESS + ", " + + GENNAME_CHOICE_REGISTEREDID + "." + } + )); + } + return theGeneralNameChoice; + } + + static public class GeneralNamesConfig implements IGeneralNamesConfig { + public String mName = null; // substore name of config if any. + public GeneralNameConfig[] mGenNameConfigs = null; + public IConfigStore mConfig = null; + public boolean mIsValueConfigured = true; + public boolean mIsPolicyEnabled = true; + public int mDefNumGenNames = DEF_NUM_GENERALNAMES; + public GeneralNames mGeneralNames = null; + + private String mNameDotGeneralName = mName + DOT + PROP_GENERALNAME; + + public GeneralNamesConfig( + String name, + IConfigStore config, + boolean isValueConfigured, + boolean isPolicyEnabled) + throws EBaseException { + mIsValueConfigured = isValueConfigured; + mIsPolicyEnabled = isPolicyEnabled; + mName = name; + if (mName != null) + mNameDotGeneralName = mName + DOT + PROP_GENERALNAME; + else + mNameDotGeneralName = PROP_GENERALNAME; + mConfig = config; + + int numGNs = mConfig.getInteger(PROP_NUM_GENERALNAMES); + + if (numGNs < 0) { + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + new String[] { + PROP_NUM_GENERALNAMES + "=" + numGNs, + "value must be greater than or equal to 0." } + )); + } + mGenNameConfigs = new GeneralNameConfig[numGNs]; + for (int i = 0; i < numGNs; i++) { + String storeName = mNameDotGeneralName + i; + + mGenNameConfigs[i] = + newGeneralNameConfig( + storeName, mConfig.getSubStore(storeName), + mIsValueConfigured, mIsPolicyEnabled); + } + + if (mIsValueConfigured && mIsPolicyEnabled) { + mGeneralNames = new GeneralNames(); + for (int j = 0; j < numGNs; j++) { + mGeneralNames.addElement(mGenNameConfigs[j].mGeneralName); + } + } + } + + public GeneralNames getGeneralNames() { + return mGeneralNames; + } + + protected GeneralNameConfig newGeneralNameConfig( + String name, IConfigStore config, + boolean isValueConfigured, boolean isPolicyEnabled) + throws EBaseException { + return new GeneralNameConfig( + name, config, isValueConfigured, isPolicyEnabled); + } + + public GeneralNameConfig[] getGenNameConfig() { + return (GeneralNameConfig[]) mGenNameConfigs.clone(); + } + + public int getNumGeneralNames() { + return mGenNameConfigs.length; + } + + public IConfigStore getConfig() { + return mConfig; + } + + public String getName() { + return mName; + } + + public boolean isValueConfigured() { + return mIsValueConfigured; + } + + public void setDefNumGenNames(int defNum) { + mDefNumGenNames = defNum; + } + + public int getDefNumGenNames() { + return mDefNumGenNames; + } + + /** + * adds params to default + */ + public static void getDefaultParams( + String name, boolean isValueConfigured, Vector<String> params) { + String nameDot = ""; + + if (name != null) + nameDot = name + DOT; + params.addElement( + nameDot + PROP_NUM_GENERALNAMES + '=' + DEF_NUM_GENERALNAMES); + for (int i = 0; i < DEF_NUM_GENERALNAMES; i++) { + GeneralNameConfig.getDefaultParams( + nameDot + PROP_GENERALNAME + i, isValueConfigured, params); + } + } + + /** + * Get instance params. + */ + public void getInstanceParams(Vector<String> params) { + params.addElement( + PROP_NUM_GENERALNAMES + '=' + mGenNameConfigs.length); + for (int i = 0; i < mGenNameConfigs.length; i++) { + mGenNameConfigs[i].getInstanceParams(params); + } + } + + /** + * Get extended plugin info. + */ + public static void getExtendedPluginInfo( + String name, boolean isValueConfigured, Vector<String> info) { + String nameDot = ""; + + if (name != null && name.length() > 0) + nameDot = name + "."; + info.addElement(PROP_NUM_GENERALNAMES + ";" + NUM_GENERALNAMES_INFO); + for (int i = 0; i < DEF_NUM_GENERALNAMES; i++) { + GeneralNameConfig.getExtendedPluginInfo( + nameDot + PROP_GENERALNAME + i, isValueConfigured, info); + } + } + + } + + static public class GeneralNamesAsConstraintsConfig extends GeneralNamesConfig implements + IGeneralNamesAsConstraintsConfig { + public GeneralNamesAsConstraintsConfig( + String name, + IConfigStore config, + boolean isValueConfigured, + boolean isPolicyEnabled) + throws EBaseException { + super(name, config, isValueConfigured, isPolicyEnabled); + } + + protected GeneralNameConfig newGeneralNameConfig( + String name, IConfigStore config, + boolean isValueConfigured, boolean isPolicyEnabled) + throws EBaseException { + return new GeneralNameAsConstraintsConfig(name, config, + isValueConfigured, isPolicyEnabled); + } + } + + /** + * convenience class for policies use. + */ + static public class GeneralNameConfig implements IGeneralNameConfig { + public String mName = null; + public String mNameDot = null; + public IConfigStore mConfig = null; + public String mGenNameChoice = null; + public boolean mIsValueConfigured = true; + public String mValue = null; // used only if isValueConfigured + public GeneralName mGeneralName = null; // used only if isValueConfiged. + public boolean mIsPolicyEnabled = true; + + public String mNameDotChoice = null; + public String mNameDotValue = null; + + public GeneralNameConfig( + String name, + IConfigStore config, + boolean isValueConfigured, + boolean isPolicyEnabled) + throws EBaseException { + mIsValueConfigured = isValueConfigured; + mIsPolicyEnabled = isPolicyEnabled; + mName = name; + if (mName != null && mName.length() > 0) { + mNameDot = mName + DOT; + mNameDotChoice = mNameDot + PROP_GENNAME_CHOICE; + mNameDotValue = mNameDot + PROP_GENNAME_VALUE; + } else { + mNameDot = ""; + mNameDotChoice = PROP_GENNAME_CHOICE; + mNameDotValue = PROP_GENNAME_VALUE; + } + mConfig = config; + + // necessary to expand/shrink # general names from console. + if (mConfig.size() == 0) { + config.putString(mNameDotChoice, ""); + if (mIsValueConfigured) + config.putString(mNameDotValue, ""); + } + + String choice = null; + + if (mIsPolicyEnabled) { + choice = mConfig.getString(PROP_GENNAME_CHOICE); + mGenNameChoice = check_GeneralNameChoice(choice); + } else { + choice = mConfig.getString(PROP_GENNAME_CHOICE, ""); + if (choice.length() > 0 && !choice.equals("null")) { + mGenNameChoice = check_GeneralNameChoice(choice); + } + } + if (mIsValueConfigured) { + if (mIsPolicyEnabled) { + mValue = mConfig.getString(PROP_GENNAME_VALUE); + mGeneralName = formGeneralName(mGenNameChoice, mValue); + } else { + mValue = mConfig.getString(PROP_GENNAME_VALUE, ""); + if (mValue != null && mValue.length() > 0) + mGeneralName = formGeneralName(mGenNameChoice, mValue); + } + } + } + + /** + * Form a general name from the value string. + */ + public GeneralName formGeneralName(String value) + throws EBaseException { + return formGeneralName(mGenNameChoice, value); + } + + public GeneralName formGeneralName(String choice, String value) + throws EBaseException { + return form_GeneralName(choice, value); + } + + /** + * @return a vector of General names from a value that can be + * either a Vector of strings, string array or just a string. + * Returned Vector can be null if value is not of expected type. + */ + public Vector<GeneralName> formGeneralNames(Object value) + throws EBaseException { + Vector<GeneralName> gns = new Vector<GeneralName>(); + GeneralName gn = null; + + if (value instanceof String) { + if (((String) (value = ((String) value).trim())).length() > 0) { + gn = formGeneralName(mGenNameChoice, (String) value); + gns.addElement(gn); + } + } else if (value instanceof String[]) { + String[] vals = (String[]) value; + + for (int i = 0; i < vals.length; i++) { + String val = vals[i].trim(); + + if (val != null && val.length() > 0) { + gn = formGeneralName(mGenNameChoice, val); + gns.addElement(gn); + } + } + } else if (value instanceof Vector) { + Vector<?> vals = (Vector<?>) value; + + for (Enumeration<?> n = vals.elements(); n.hasMoreElements();) { + Object val = n.nextElement(); + + if (val != null && (val instanceof String) && + ((String) (val = ((String) val).trim())).length() > 0) { + gn = formGeneralName(mGenNameChoice, (String) val); + gns.addElement(gn); + } + } + } + return gns; + } + + public String getName() { + return mName; + } + + public IConfigStore getConfig() { + return mConfig; + } + + public String getGenNameChoice() { + return mGenNameChoice; + } + + public String getValue() { + return mValue; + } + + /* + public GeneralNameInterface getGeneralName() { + return mGeneralName; + } + + */ + public boolean isValueConfigured() { + return mIsValueConfigured; + } + + /** + * Get default params + */ + + public static void getDefaultParams( + String name, boolean isValueConfigured, Vector<String> params) { + String nameDot = ""; + + if (name != null) + nameDot = name + "."; + Debug.trace("GeneralnameConfig getDefaultParams"); + params.addElement(nameDot + PROP_GENNAME_CHOICE + "="); + if (isValueConfigured) + params.addElement(nameDot + PROP_GENNAME_VALUE + "="); + } + + /** + * Get instance params + */ + public void getInstanceParams(Vector<String> params) { + String value = (mValue == null) ? "" : mValue; + String choice = (mGenNameChoice == null) ? "" : mGenNameChoice; + + params.addElement(mNameDotChoice + "=" + choice); + if (mIsValueConfigured) + params.addElement(mNameDotValue + "=" + value); + } + + /** + * Get extended plugin info + */ + public static void getExtendedPluginInfo( + String name, boolean isValueConfigured, Vector<String> info) { + String nameDot = ""; + + if (name != null && name.length() > 0) + nameDot = name + "."; + info.addElement( + nameDot + PROP_GENNAME_CHOICE + ";" + GENNAME_CHOICE_INFO); + if (isValueConfigured) + info.addElement( + nameDot + PROP_GENNAME_VALUE + ";" + GENNAME_VALUE_INFO); + } + } + + /** + * convenience class for policies use. + */ + static public class GeneralNameAsConstraintsConfig extends GeneralNameConfig implements + IGeneralNameAsConstraintsConfig { + + public GeneralNameAsConstraintsConfig( + String name, + IConfigStore config, + boolean isValueConfigured, + boolean isPolicyEnabled) + throws EBaseException { + super(name, config, isValueConfigured, isPolicyEnabled); + } + + public GeneralName getGeneralName() { + return mGeneralName; + } + + /** + * Form a general name from the value string. + */ + public GeneralName formGeneralName(String choice, String value) + throws EBaseException { + return form_GeneralNameAsConstraints(choice, value); + } + } + + public static class SubjAltNameGN extends GeneralNameUtil.GeneralNameConfig implements ISubjAltNameConfig { + static final String REQUEST_ATTR_INFO = + "string;Request attribute name. " + + "The value of the request attribute will be used to form a " + + "General Name in the Subject Alternative Name extension."; + + static final String PROP_REQUEST_ATTR = "requestAttr"; + + String mRequestAttr = null; + String mPfx = null; + String mAttr = null; + + public SubjAltNameGN( + String name, IConfigStore config, boolean isPolicyEnabled) + throws EBaseException { + super(name, config, false, isPolicyEnabled); + + mRequestAttr = mConfig.getString(PROP_REQUEST_ATTR, null); + if (mRequestAttr == null) { + mConfig.putString(mNameDot + PROP_REQUEST_ATTR, ""); + mRequestAttr = ""; + } + if (isPolicyEnabled && mRequestAttr.length() == 0) { + throw new EPropertyNotFound(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", + mConfig.getName() + "." + PROP_REQUEST_ATTR)); + } + int x = mRequestAttr.indexOf('.'); + + if (x == -1) + mAttr = mRequestAttr; + else { + mPfx = mRequestAttr.substring(0, x).trim(); + mAttr = mRequestAttr.substring(x + 1).trim(); + } + } + + public String getPfx() { + return mPfx; + } + + public String getAttr() { + return mAttr; + } + + public void getInstanceParams(Vector<String> params) { + params.addElement(mNameDot + PROP_REQUEST_ATTR + "=" + mRequestAttr); + super.getInstanceParams(params); + } + + public static void getDefaultParams(String name, Vector<String> params) { + String nameDot = ""; + + if (name != null && name.length() > 0) + nameDot = name + "."; + params.addElement(nameDot + PROP_REQUEST_ATTR + "="); + GeneralNameUtil.GeneralNameConfig.getDefaultParams(name, false, params); + } + + public static void getExtendedPluginInfo(String name, Vector<String> params) { + String nameDot = ""; + + if (name != null && name.length() > 0) + nameDot = name + "."; + params.addElement(nameDot + PROP_REQUEST_ATTR + ";" + REQUEST_ATTR_INFO); + GeneralNameUtil.GeneralNameConfig.getExtendedPluginInfo(name, false, params); + } + } +} diff --git a/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java b/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java new file mode 100644 index 000000000..05f8e111a --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java @@ -0,0 +1,1548 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.policy; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.StringTokenizer; +import java.util.Vector; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.common.Constants; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.policy.IExpression; +import com.netscape.certsrv.policy.IKeyArchivalPolicy; +import com.netscape.certsrv.policy.IKeyRecoveryPolicy; +import com.netscape.certsrv.policy.IPolicyProcessor; +import com.netscape.certsrv.policy.IPolicyRule; +import com.netscape.certsrv.policy.IPolicySet; +import com.netscape.certsrv.policy.IRenewalPolicy; +import com.netscape.certsrv.policy.IRevocationPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cmscore.base.PropConfigStore; +import com.netscape.cmscore.base.SubsystemRegistry; +import com.netscape.cmscore.request.ARequestQueue; +import com.netscape.cmscore.util.AssertionException; +import com.netscape.cmscore.util.Debug; + +/** + * This is a Generic policy processor. The three main functions of + * this class are: + * 1. To initialize policies by reading policy configuration from the + * config file, and maintain 5 sets of policies - viz Enrollment, + * Renewal, Revocation and KeyRecovery and KeyArchival. + * 2. To apply the configured policies on the given request. + * 3. To enable policy listing/configuration via MCC console. + * + * Since the policy processor also implements the IPolicy interface + * the processor itself presents itself as one big policy to the + * request processor. + * + * @deprecated + * @author kanda + * @version $Revision$, $Date$ + */ +public class GenericPolicyProcessor implements IPolicyProcessor { + protected IConfigStore mConfig = null; + protected IConfigStore mGlobalStore = null; + protected IAuthority mAuthority = null; + + // Default System Policies + public final static String[] DEF_POLICIES = + { "com.netscape.cms.policy.constraints.ManualAuthentication" }; + + // Policies that can't be deleted nor disabled. + public final static Hashtable<String, IExpression> DEF_UNDELETABLE_POLICIES = + new Hashtable<String, IExpression>(); + + private String mId = "Policy"; + private Vector<String> mPolicyOrder = new Vector<String>(); + private Hashtable<String, RegisteredPolicy> mImplTable = new Hashtable<String, RegisteredPolicy>(); + private Hashtable<String, PolicyInstance> mInstanceTable = new Hashtable<String, PolicyInstance>(); + PolicySet mEnrollmentRules = new PolicySet("EnrollmentRules"); + PolicySet mRenewalRules = new PolicySet("RenewalRules"); + PolicySet mRevocationRules = new PolicySet("RevocationRules"); + PolicySet mKeyRecoveryRules = new PolicySet("KeyRecoveryRules"); + PolicySet mKeyArchivalRules = new PolicySet("KeyArchivalRules"); + private String[] mSystemDefaults = null; + private boolean mInitSystemPolicies; + + // A Table of persistent policies and their predicates. + // The predicates cannot be changed during configuration. + private Hashtable<String, IExpression> mUndeletablePolicies = null; + + public GenericPolicyProcessor() { + mInitSystemPolicies = true; // CA & RA + } + + public GenericPolicyProcessor(boolean initSystemPolicies) { + mInitSystemPolicies = initSystemPolicies; // KRA + } + + public void setId(String id) throws EBaseException { + mId = id; + } + + public String getId() { + return mId; + } + + public void startup() throws EBaseException { + } + + /** + * Shuts down this subsystem. + * <P> + */ + public void shutdown() { + } + + public ISubsystem getAuthority() { + return mAuthority; + } + + /** + * Returns the configuration store. + * <P> + * + * @return configuration store + */ + public IConfigStore getConfigStore() { + return mConfig; + } + + /** + * Initializes the PolicyProcessor + * <P> + * + * @param owner owner of this subsystem + * @param config configuration of this subsystem + * @exception EBaseException failed to initialize this Subsystem. + */ + public synchronized void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + // Debug.trace("GenericPolicyProcessor::init"); + CMS.debug("GenericPolicyProcessor::init begins"); + mAuthority = (IAuthority) owner; + mConfig = config; + mGlobalStore = + SubsystemRegistry.getInstance().get("MAIN").getConfigStore(); + + try { + IConfigStore configStore = CMS.getConfigStore(); + String PKI_Subsystem = configStore.getString("subsystem.0.id", + null); + + // CMS 6.1 began utilizing the "Certificate Profiles" framework + // instead of the legacy "Certificate Policies" framework. + // + // Beginning with CS 8.1, to meet the Common Criteria evaluation + // performed on this version of the product, it was determined + // that this legacy "Certificate Policies" framework would be + // deprecated and disabled by default (see Bugzilla Bug #472597). + // + // NOTE: The "Certificate Policies" framework ONLY applied to + // to CA, KRA, and legacy RA (pre-CMS 7.0) subsystems. + // + if (PKI_Subsystem.trim().equalsIgnoreCase("ca") || + PKI_Subsystem.trim().equalsIgnoreCase("kra")) { + String policyStatus = PKI_Subsystem.trim().toLowerCase() + + "." + "Policy" + + "." + IPolicyProcessor.PROP_ENABLE; + + if (configStore.getBoolean(policyStatus, true) == true) { + // NOTE: If "<subsystem>.Policy.enable=<boolean>" is + // missing, then the referenced instance existed + // prior to this name=value pair existing in its + // 'CS.cfg' file, and thus we err on the + // side that the user may still need to + // use the policy framework. + CMS.debug("GenericPolicyProcessor::init Certificate " + + "Policy Framework (deprecated) " + + "is ENABLED"); + } else { + // CS 8.1 Default: <subsystem>.Policy.enable=false + CMS.debug("GenericPolicyProcessor::init Certificate " + + "Policy Framework (deprecated) " + + "is DISABLED"); + return; + } + } + } catch (EBaseException e) { + throw e; + } + + // Initialize default policies system that would be + // present in the system always. + if (mInitSystemPolicies) { + initSystemPolicies(mConfig); + } + + // Read listing of undeletable policies if any. + initUndeletablePolicies(mConfig); + + // Read all registered policies first.. + IConfigStore c; + + c = config.getSubStore(PROP_IMPL); + Enumeration<String> mImpls = c.getSubStoreNames(); + + while (mImpls.hasMoreElements()) { + String id = (String) mImpls.nextElement(); + + // The implementation id should be unique + if (mImplTable.containsKey(id)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_DUPLICATE_IMPL_ID", id)); + + String clPath = c.getString(id + "." + PROP_CLASS); + + // We should n't let the CatchAll policies to be configurable. + if (isSystemDefaultPolicy(clPath)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_SYSTEM_POLICY_CONFIG_ERROR", clPath)); + + // Verify if the class is a valid implementation of + // IPolicyRule + try { + Object o = Class.forName(clPath).newInstance(); + + if (!(o instanceof IEnrollmentPolicy) && + !(o instanceof IRenewalPolicy) && + !(o instanceof IRevocationPolicy) && + !(o instanceof IKeyRecoveryPolicy) && + !(o instanceof IKeyArchivalPolicy)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL", clPath)); + } catch (EBaseException e) { + throw e; + } catch (Exception e) { + Debug.printStackTrace(e); + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL", + id)); + } + + // Register the implementation. + RegisteredPolicy regPolicy = + new RegisteredPolicy(id, clPath); + + mImplTable.put(id, regPolicy); + } + + // Now read the priority ordering of rule configurations. + String policyOrder = config.getString(PROP_ORDER, null); + + if (policyOrder == null) { + return; + // throw new EPolicyException(PolicyResources.NO_POLICY_ORDERING); + } else { + StringTokenizer tokens = new StringTokenizer(policyOrder, ","); + + while (tokens.hasMoreTokens()) { + mPolicyOrder.addElement(tokens.nextToken().trim()); + } + } + + // Now Read Policy configurations and construct policy objects + int numPolicies = mPolicyOrder.size(); + IConfigStore ruleStore = config.getSubStore(PROP_RULE); + + for (int i = 0; i < numPolicies; i++) { + String instanceName = (String) mPolicyOrder.elementAt(i); + + // The instance id should be unique + if (mInstanceTable.containsKey(instanceName)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_DUPLICATE_INST_ID", instanceName)); + + c = ruleStore.getSubStore(instanceName); + if (c == null || c.size() == 0) + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_CONFIG", + instanceName)); + IPolicyRule rule = null; + String implName; + boolean enabled; + IExpression filterExp; + + // If the policy rule is not enabled, skip it. + String enabledStr = c.getString(PROP_ENABLE, null); + + if (enabledStr == null || enabledStr.trim().length() == 0 || + enabledStr.trim().equalsIgnoreCase("true")) + enabled = true; + else + enabled = false; + + implName = c.getString(PROP_IMPL_NAME, null); + if (implName == null) { + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_CONFIG", + instanceName)); + } + + // Make an instance of the specified policy. + RegisteredPolicy regPolicy = + (RegisteredPolicy) mImplTable.get(implName); + + if (regPolicy == null) { + String[] params = { implName, instanceName }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_IMPL_NOT_FOUND", params)); + } + + String classpath = regPolicy.getClassPath(); + + try { + rule = (IPolicyRule) + Class.forName(classpath).newInstance(); + if (rule instanceof IPolicyRule) + ((IPolicyRule) rule).setInstanceName(instanceName); + rule.init(this, c); + } catch (Throwable e) { + mAuthority.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_POLICY_INIT_FAILED", instanceName, e.toString())); + // disable rule initialized if there is + // configuration error + enabled = false; + c.putString(PROP_ENABLE, "false"); + } + + if (rule == null) + continue; + + // Read the predicate expression if any associated + // with the rule + String exp = c.getString(GenericPolicyProcessor.PROP_PREDICATE, null); + + if (exp != null) + exp = exp.trim(); + if (exp != null && exp.length() > 0) { + filterExp = PolicyPredicateParser.parse(exp); + rule.setPredicate(filterExp); + } + + // Add the rule to the instance table + mInstanceTable.put(instanceName, + new PolicyInstance(instanceName, implName, rule, enabled)); + + if (!enabled) + continue; + + // Add the rule to the policy set according to category if a + // rule is enabled. + addRule(instanceName, rule); + } + + // Verify that the default policies are present and enabled. + verifyDefaultPolicyConfig(); + + // printPolicies(); + } + + public boolean isProfileRequest(IRequest request) { + String profileId = request.getExtDataInString("profileId"); + + if (profileId == null || profileId.equals("")) + return false; + else + return true; + } + + /** + * Apply policies on the given request. + * + * @param IRequest The given request + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + IPolicySet rules = null; + String op = (String) req.getRequestType(); + + CMS.debug("GenericPolicyProcessor: apply begins"); + if (op == null) { + CMS.debug("GenericPolicyProcessor: apply op null"); + // throw new AssertionException("Missing operation type in request. Can't happen!"); + // Return ACCEPTED for now. Looks like even get CA chain + // is being passed in here with request type set elsewhere + // on the request. + return PolicyResult.ACCEPTED; + } + if (isProfileRequest(req)) { + Debug.trace("GenericPolicyProcessor: Profile-base Request " + + req.getRequestId().toString()); + return PolicyResult.ACCEPTED; + } + CMS.debug("GenericPolicyProcessor: apply not ProfileRequest. op=" + op); + + if (op.equalsIgnoreCase(IRequest.ENROLLMENT_REQUEST)) + rules = mEnrollmentRules; + else if (op.equalsIgnoreCase(IRequest.RENEWAL_REQUEST)) + rules = mRenewalRules; + else if (op.equalsIgnoreCase(IRequest.REVOCATION_REQUEST)) + rules = mRevocationRules; + else if (op.equalsIgnoreCase(IRequest.KEY_RECOVERY_REQUEST)) + rules = mKeyRecoveryRules; + else if (op.equalsIgnoreCase(IRequest.KEY_ARCHIVAL_REQUEST)) + rules = mKeyArchivalRules; + else { + // It aint' a CMP request. We don't care. + return PolicyResult.ACCEPTED; + // throw new AssertionException("Invalid request type. Can't Happen!"); + } + + // ((PolicySet)rules).printPolicies(); + // If there are no rules, then it is a serious error. + if (rules.count() == 0) { + CMS.debug("GenericPolicyProcessor: apply: rule count 0"); + // if no policy is specified, just accept the request. + // KRA has no policy configured by default + return PolicyResult.ACCEPTED; + + /** + * setError(req, PolicyResources.NO_RULES_CONFIGURED, op); + * return PolicyResult.REJECTED; + **/ + } + CMS.debug("GenericPolicyProcessor: apply: rules.count=" + rules.count()); + + // request must be up to date or can't process it. + PolicyResult res = PolicyResult.ACCEPTED; + String mVersion = ARequestQueue.REQUEST_VERSION; + String vers = req.getRequestVersion(); + + if (vers == null || !vers.equals(mVersion)) { + if (vers == null || vers.length() == 0) + vers = "none"; + res = PolicyResult.REJECTED; + } + + if (res == PolicyResult.REJECTED) + return res; + + CMS.debug("GenericPolicyProcessor: apply: calling rules.apply()"); + // Apply the policy rules. + return rules.apply(req); + } + + public void printPolicies() { + mEnrollmentRules.printPolicies(); + mRenewalRules.printPolicies(); + mRevocationRules.printPolicies(); + mKeyRecoveryRules.printPolicies(); + mKeyArchivalRules.printPolicies(); + } + + public String getPolicySubstoreId() { + return mAuthority.getId() + ".Policy"; + } + + public Enumeration<IPolicyRule> getPolicyImpls() { + Vector<IPolicyRule> impls = new Vector<IPolicyRule>(); + Enumeration<RegisteredPolicy> enum1 = mImplTable.elements(); + Enumeration<IPolicyRule> ret = null; + + try { + while (enum1.hasMoreElements()) { + RegisteredPolicy regPolicy = + (RegisteredPolicy) enum1.nextElement(); + + // Make an Instance of it + IPolicyRule ruleImpl = (IPolicyRule) + Class.forName(regPolicy.getClassPath()).newInstance(); + + impls.addElement(ruleImpl); + } + ret = impls.elements(); + } catch (Exception e) { + Debug.printStackTrace(e); + } + return ret; + } + + public Enumeration<String> getPolicyImplsInfo() { + Vector<String> impls = new Vector<String>(); + Enumeration<RegisteredPolicy> enum1 = mImplTable.elements(); + Enumeration<String> ret = null; + + try { + while (enum1.hasMoreElements()) { + RegisteredPolicy regPolicy = + (RegisteredPolicy) enum1.nextElement(); + + impls.addElement(regPolicy.getId()); + + } + ret = impls.elements(); + } catch (Exception e) { + Debug.printStackTrace(e); + } + return ret; + } + + public IPolicyRule getPolicyImpl(String id) { + RegisteredPolicy regImpl = (RegisteredPolicy) + mImplTable.get(id); + + if (regImpl == null) + return null; + IPolicyRule impl = null; + + try { + impl = + (IPolicyRule) Class.forName(regImpl.getClassPath()).newInstance(); + } catch (Exception e) { + Debug.printStackTrace(e); + } + return impl; + } + + public Vector<String> getPolicyImplConfig(String id) { + IPolicyRule rp = getPolicyImpl(id); + + if (rp == null) + return null; + Vector<String> v = rp.getDefaultParams(); + + if (v == null) + v = new Vector<String>(); + v.insertElementAt(IPolicyRule.PROP_ENABLE + "=" + "true", 0); + v.insertElementAt(IPolicyRule.PROP_PREDICATE + "=" + " ", 1); + return v; + } + + public void deletePolicyImpl(String id) + throws EBaseException { + // First check if the id is valid; + RegisteredPolicy regPolicy = + (RegisteredPolicy) mImplTable.get(id); + + if (regPolicy == null) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL", id)); + + // If any instance exists for this impl, can't delete it. + boolean instanceExist = false; + Enumeration<PolicyInstance> e = mInstanceTable.elements(); + + for (; e.hasMoreElements();) { + PolicyInstance inst = (PolicyInstance) e.nextElement(); + + if (inst.isInstanceOf(id)) { + instanceExist = true; + break; + } + } + if (instanceExist) // we found an instance + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_ACTIVE_POLICY_RULES_EXIST", id)); + + // Else delete the implementation + mImplTable.remove(id); + IConfigStore policyStore = + mGlobalStore.getSubStore(getPolicySubstoreId()); + IConfigStore implStore = + policyStore.getSubStore(PROP_IMPL); + + implStore.removeSubStore(id); + + // committing + try { + mGlobalStore.commit(true); + } catch (Exception ex) { + Debug.printStackTrace(ex); + String[] params = { "implementation", id }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_DELETING_POLICY_ERROR", params)); + } + } + + public void addPolicyImpl(String id, String classPath) + throws EBaseException { + // See if the id is unique + if (mImplTable.containsKey(id)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_DUPLICATE_IMPL_ID", id)); + + // See if the classPath is ok + Object impl = null; + + try { + impl = Class.forName(classPath).newInstance(); + } catch (Exception e) { + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL", + id)); + } + + // Does the class implement one of the four interfaces? + if (!(impl instanceof IEnrollmentPolicy) && + !(impl instanceof IRenewalPolicy) && + !(impl instanceof IRevocationPolicy) && + !(impl instanceof IKeyRecoveryPolicy) && + !(impl instanceof IKeyArchivalPolicy)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL", classPath)); + + // Add the implementation to the registry + RegisteredPolicy regPolicy = + new RegisteredPolicy(id, classPath); + + mImplTable.put(id, regPolicy); + + // Store the impl in the configuration. + IConfigStore policyStore = + mGlobalStore.getSubStore(getPolicySubstoreId()); + IConfigStore implStore = + policyStore.getSubStore(PROP_IMPL); + IConfigStore newStore = implStore.makeSubStore(id); + + newStore.put(PROP_CLASS, classPath); + try { + mGlobalStore.commit(true); + } catch (Exception e) { + String[] params = { "implementation", id }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_ADDING_POLICY_ERROR", params)); + } + } + + public Enumeration<IPolicyRule> getPolicyInstances() { + Vector<IPolicyRule> rules = new Vector<IPolicyRule>(); + Enumeration<String> enum1 = mPolicyOrder.elements(); + Enumeration<IPolicyRule> ret = null; + + try { + while (enum1.hasMoreElements()) { + PolicyInstance instance = + (PolicyInstance) mInstanceTable.get((String) enum1.nextElement()); + + rules.addElement(instance.getRule()); + + } + ret = rules.elements(); + } catch (Exception e) { + Debug.printStackTrace(e); + } + return ret; + } + + public Enumeration<String> getPolicyInstancesInfo() { + Vector<String> rules = new Vector<String>(); + Enumeration<String> enum1 = mPolicyOrder.elements(); + Enumeration<String> ret = null; + + try { + while (enum1.hasMoreElements()) { + String ruleName = enum1.nextElement(); + PolicyInstance instance = mInstanceTable.get(ruleName); + rules.addElement(instance.getRuleInfo()); + } + ret = rules.elements(); + } catch (Exception e) { + Debug.printStackTrace(e); + } + return ret; + } + + public IPolicyRule getPolicyInstance(String id) { + PolicyInstance policyInstance = (PolicyInstance) + mInstanceTable.get(id); + + return (policyInstance == null) ? null : policyInstance.getRule(); + } + + public Vector<String> getPolicyInstanceConfig(String id) { + PolicyInstance policyInstance = (PolicyInstance) + mInstanceTable.get(id); + + if (policyInstance == null) + return null; + Vector<String> v = policyInstance.getRule().getInstanceParams(); + + if (v == null) + v = new Vector<String>(); + v.insertElementAt(PROP_IMPL_NAME + "=" + policyInstance.getImplId(), 0); + v.insertElementAt(PROP_ENABLE + "=" + policyInstance.isActive(), 1); + String predicate = " "; + + if (policyInstance.getRule().getPredicate() != null) + predicate = policyInstance.getRule().getPredicate().toString(); + v.insertElementAt(PROP_PREDICATE + "=" + predicate, 2); + return v; + } + + public void deletePolicyInstance(String id) + throws EBaseException { + // If the rule is a persistent rule, we can't delete it. + if (mUndeletablePolicies.containsKey(id)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_CANT_DELETE_PERSISTENT_POLICY", id)); + + // First check if the instance is present. + PolicyInstance instance = + (PolicyInstance) mInstanceTable.get(id); + + if (instance == null) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_INSTANCE", id)); + + IConfigStore policyStore = + mGlobalStore.getSubStore(getPolicySubstoreId()); + IConfigStore instanceStore = + policyStore.getSubStore(PROP_RULE); + + instanceStore.removeSubStore(id); + + // Remove the rulename from the rder list + int index = mPolicyOrder.indexOf(id); + + mPolicyOrder.removeElement(id); + + // Now change the ordering in the config file. + policyStore.put(PROP_ORDER, getRuleOrderString(mPolicyOrder)); + + // Commit changes to file. + try { + mGlobalStore.commit(true); + } catch (Exception e) { + // Put the rule back in the rule order vector. + mPolicyOrder.insertElementAt(id, index); + + Debug.printStackTrace(e); + String[] params = { "instance", id }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_DELETING_POLICY_ERROR", params)); + } + + IPolicyRule rule = instance.getRule(); + + if (rule instanceof IEnrollmentPolicy) + mEnrollmentRules.removeRule(id); + if (rule instanceof IRenewalPolicy) + mRenewalRules.removeRule(id); + if (rule instanceof IRevocationPolicy) + mRevocationRules.removeRule(id); + if (rule instanceof IKeyRecoveryPolicy) + mKeyRecoveryRules.removeRule(id); + if (rule instanceof IKeyArchivalPolicy) + mKeyArchivalRules.removeRule(id); + + // Delete the instance + mInstanceTable.remove(id); + } + + public void addPolicyInstance(String id, Hashtable<String, String> ht) + throws EBaseException { + // The instance id should be unique + if (getPolicyInstance(id) != null) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_DUPLICATE_INST_ID", id)); + // There should be an implmentation for this rule. + String implName = (String) ht.get(IPolicyRule.PROP_IMPLNAME); + + // See if there is an implementation with this name. + IPolicyRule rule = getPolicyImpl(implName); + + if (rule == null) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL", implName)); + + // Prepare config file entries. + IConfigStore policyStore = + mGlobalStore.getSubStore(getPolicySubstoreId()); + IConfigStore instanceStore = + policyStore.getSubStore(PROP_RULE); + IConfigStore newStore = instanceStore.makeSubStore(id); + + for (Enumeration<String> keys = ht.keys(); keys.hasMoreElements();) { + String key = keys.nextElement(); + String val = ht.get(key); + + newStore.put(key, val); + } + + // Set the order string. + policyStore.put(PROP_ORDER, + getRuleOrderString(mPolicyOrder, id)); + + // Try to initialize this rule. + rule.init(this, newStore); + + // Add the rule to the table. + String enabledStr = (String) ht.get(IPolicyRule.PROP_ENABLE); + boolean active = false; + + if (enabledStr == null || enabledStr.trim().length() == 0 || + enabledStr.equalsIgnoreCase("true")) + active = true; + + // Set the predicate if any present on the rule. + String predicate = ((String) ht.get(IPolicyRule.PROP_PREDICATE)).trim(); + IExpression exp = null; + + if (predicate.trim().length() > 0) + exp = PolicyPredicateParser.parse(predicate.trim()); + rule.setPredicate(exp); + + // Store the changes in the file. + try { + mGlobalStore.commit(true); + } catch (Exception e) { + String[] params = { "instance", id }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_ADDING_POLICY_ERROR", params)); + } + + // Add the rule to the instance table. + PolicyInstance policyInst = new PolicyInstance(id, implName, + rule, active); + + mInstanceTable.put(id, policyInst); + + // Add the rule to the end of order table. + mPolicyOrder.addElement(id); + + // If the rule is not active, return. + if (!active) + return; + + addRule(id, rule); + } + + public void modifyPolicyInstance(String id, Hashtable<String, String> ht) + throws EBaseException { + // The instance id should be there already + PolicyInstance policyInstance = (PolicyInstance) + mInstanceTable.get(id); + + if (policyInstance == null) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_INSTANCE", id)); + IPolicyRule rule = policyInstance.getRule(); + + // The impl id shouldn't change + String implId = (String) ht.get(IPolicyRule.PROP_IMPLNAME); + + if (!implId.equals(policyInstance.getImplId())) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_IMPLCHANGE_ERROR", id)); + + // Make a new rule instance + IPolicyRule newRule = getPolicyImpl(implId); + + if (newRule == null) // Can't happen, but just in case.. + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL", implId)); + + // Try to init this rule. + IConfigStore policyStore = + mGlobalStore.getSubStore(getPolicySubstoreId()); + IConfigStore instanceStore = + policyStore.getSubStore(PROP_RULE); + IConfigStore oldStore = instanceStore.getSubStore(id); + IConfigStore newStore = new PropConfigStore(id); + + // See if the rule is disabled. + String enabledStr = (String) ht.get(IPolicyRule.PROP_ENABLE); + boolean active = false; + + if (enabledStr == null || enabledStr.trim().length() == 0 || + enabledStr.equalsIgnoreCase("true")) + active = true; + + // Set the predicate expression. + String predicate = ((String) ht.get(IPolicyRule.PROP_PREDICATE)).trim(); + IExpression exp = null; + + if (predicate.trim().length() > 0) + exp = PolicyPredicateParser.parse(predicate.trim()); + + // See if this a persistent rule. + if (mUndeletablePolicies.containsKey(id)) { + // A persistent rule can't be disabled. + if (!active) { + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_INACTIVE", id)); + } + + IExpression defPred = (IExpression) + mUndeletablePolicies.get(id); + + if (defPred == SimpleExpression.NULL_EXPRESSION) + defPred = null; + if (exp == null && defPred != null) { + String[] params = { id, defPred.toString(), + "null" }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params)); + } else if (exp != null && defPred == null) { + String[] params = { id, "null", exp.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params)); + } else if (exp != null && defPred != null) { + if (!defPred.toString().equals(exp.toString())) { + String[] params = { id, defPred.toString(), + exp.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params)); + } + } + } + + // Predicate for the persistent rule can't be changed. + ht.put(IPolicyRule.PROP_ENABLE, String.valueOf(active)); + + // put old config store parameters first. + for (Enumeration<String> oldkeys = oldStore.keys(); oldkeys.hasMoreElements();) { + String k = (String) oldkeys.nextElement(); + String v = (String) oldStore.getString(k); + + newStore.put(k, v); + } + + // put modified params. + for (Enumeration<String> newkeys = ht.keys(); newkeys.hasMoreElements();) { + String k = (String) newkeys.nextElement(); + String v = (String) ht.get(k); + + Debug.trace("newstore key " + k + "=" + v); + if (v != null) { + if (!k.equals(Constants.OP_TYPE) && !k.equals(Constants.OP_SCOPE) && + !k.equals(Constants.RS_ID) && !k.equals("RULENAME")) { + Debug.trace("newstore.put(" + k + "=" + v + ")"); + newStore.put(k, v); + } + } + } + + // include impl default params in case we missed any. + + /* + for (Enumeration keys = ht.keys(); keys.hasMoreElements();) + { + String key = (String)keys.nextElement(); + String val = (String)ht.get(key); + newStore.put(key, val); + } + */ + + // Try to initialize this rule. + newRule.init(this, newStore); + + // If we are successfully initialized, replace the rule + // instance + policyInstance.setRule(newRule); + policyInstance.setActive(active); + + // Set the predicate expression. + if (exp != null) + newRule.setPredicate(exp); + + // Store the changes in the file. + try { + for (Enumeration<String> e = newStore.keys(); e.hasMoreElements();) { + String key = (String) e.nextElement(); + + if (key != null) { + Debug.trace( + "oldstore.put(" + key + "," + + (String) newStore.getString(key) + ")"); + oldStore.put(key, (String) newStore.getString(key)); + } + } + mGlobalStore.commit(true); + } catch (Exception e) { + String[] params = { "instance", id }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_ADDING_POLICY_ERROR", params)); + } + + // If rule is disabled, we need to remove it from the + // policy set. + if (!active) { + if (rule instanceof IEnrollmentPolicy) + mEnrollmentRules.removeRule(id); + if (rule instanceof IRenewalPolicy) + mRenewalRules.removeRule(id); + if (rule instanceof IRevocationPolicy) + mRevocationRules.removeRule(id); + if (rule instanceof IKeyRecoveryPolicy) + mKeyRecoveryRules.removeRule(id); + if (rule instanceof IKeyArchivalPolicy) + mKeyArchivalRules.removeRule(id); + } else // replace the rule + { + if (rule instanceof IEnrollmentPolicy) + mEnrollmentRules.replaceRule(id, newRule); + if (rule instanceof IRenewalPolicy) + mRenewalRules.replaceRule(id, newRule); + if (rule instanceof IRevocationPolicy) + mRevocationRules.replaceRule(id, newRule); + if (rule instanceof IKeyRecoveryPolicy) + mKeyRecoveryRules.replaceRule(id, newRule); + if (rule instanceof IKeyArchivalPolicy) + mKeyArchivalRules.replaceRule(id, newRule); + } + } + + public synchronized void changePolicyInstanceOrdering( + String policyOrderStr) + throws EBaseException { + Vector<String> policyOrder = new Vector<String>(); + StringTokenizer tokens = new StringTokenizer(policyOrderStr, ","); + + // Get all the elements + while (tokens.hasMoreTokens()) { + String instanceId = tokens.nextToken().trim(); + + // Check if we have that instance configured. + if (!mInstanceTable.containsKey(instanceId)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_INSTANCE", instanceId)); + policyOrder.addElement(instanceId); + } + + // Now enforce the new ordering + // First if the order is the same as what we have, + // return. + if (policyOrder.size() == mPolicyOrder.size()) { + if (areSameVectors(policyOrder, mPolicyOrder)) + return; + } + PolicySet enrollmentRules = new PolicySet("EnrollmentRules"); + PolicySet renewalRules = new PolicySet("RenewalRules"); + PolicySet revocationRules = new PolicySet("RevocationRules"); + PolicySet keyRecoveryRules = new PolicySet("KeyRecoveryRules"); + PolicySet keyArchivalRules = new PolicySet("KeyArchivalRules"); + + // add system default rules first. + try { + for (int i = 0; i < mSystemDefaults.length; i++) { + String defRuleName = mSystemDefaults[i].substring( + mSystemDefaults[i].lastIndexOf('.') + 1); + IPolicyRule defRule = (IPolicyRule) + Class.forName(mSystemDefaults[i]).newInstance(); + IConfigStore ruleConfig = + mConfig.getSubStore(PROP_DEF_POLICIES + "." + defRuleName); + + defRule.init(this, ruleConfig); + if (defRule instanceof IEnrollmentPolicy) + enrollmentRules.addRule(defRuleName, defRule); + else if (defRule instanceof IRenewalPolicy) + renewalRules.addRule(defRuleName, defRule); + else if (defRule instanceof IRevocationPolicy) + revocationRules.addRule(defRuleName, defRule); + else if (defRule instanceof IKeyRecoveryPolicy) + keyRecoveryRules.addRule(defRuleName, defRule); + else if (defRule instanceof IKeyArchivalPolicy) + keyArchivalRules.addRule(defRuleName, defRule); + // else ignore the darned rule. + } + } catch (Throwable e) { + Debug.printStackTrace(e); + EBaseException ex = new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", + "Cannot create default policy rule. Error: " + e.getMessage())); + + mAuthority.log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_POLICY_DEF_CREATE", e.toString())); + throw ex; + } + + // add rules specified in the new order. + for (Enumeration<String> enum1 = policyOrder.elements(); enum1.hasMoreElements();) { + String instanceName = (String) enum1.nextElement(); + PolicyInstance pInstance = (PolicyInstance) + mInstanceTable.get(instanceName); + + if (!pInstance.isActive()) + continue; + + // Add the rule to the policy set according to category if a + // rule is enabled. + IPolicyRule rule = pInstance.getRule(); + + if (rule instanceof IEnrollmentPolicy) + enrollmentRules.addRule(instanceName, rule); + else if (rule instanceof IRenewalPolicy) + renewalRules.addRule(instanceName, rule); + else if (rule instanceof IRevocationPolicy) + revocationRules.addRule(instanceName, rule); + else if (rule instanceof IKeyRecoveryPolicy) + keyRecoveryRules.addRule(instanceName, rule); + else if (rule instanceof IKeyArchivalPolicy) + keyArchivalRules.addRule(instanceName, rule); + // else ignore the darned rule. + } + + mEnrollmentRules = enrollmentRules; + mRenewalRules = renewalRules; + mRevocationRules = revocationRules; + mKeyRecoveryRules = keyRecoveryRules; + mKeyArchivalRules = keyArchivalRules; + mPolicyOrder = policyOrder; + + // Now change the ordering in the config file. + IConfigStore policyStore = + mGlobalStore.getSubStore(getPolicySubstoreId()); + + policyStore.put(PROP_ORDER, policyOrderStr); + + // committing + try { + mGlobalStore.commit(true); + } catch (Exception ex) { + Debug.printStackTrace(ex); + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_ORDER_ERROR", policyOrderStr)); + } + } + + private boolean areSameVectors(Vector<String> v1, Vector<String> v2) { + if (v1.size() != v2.size()) + return false; + int size = v1.size(); + int i = 0; + + for (; i < size; i++) + if (v2.indexOf(v1.elementAt(i)) != i) + break; + return (i == size ? true : false); + } + + private String getRuleOrderString(Vector<String> rules) { + StringBuffer sb = new StringBuffer(); + + for (Enumeration<String> e = rules.elements(); e.hasMoreElements();) { + sb.append((String) e.nextElement()); + sb.append(","); + } + if (sb.length() > 0) + sb.setLength(sb.length() - 1); + return new String(sb); + } + + private String getRuleOrderString(Vector<String> rules, String newRule) { + String currentRules = getRuleOrderString(rules); + + if (currentRules == null || currentRules.length() == 0) + return newRule; + else + return currentRules + "," + newRule; + } + + /** + * Initializes the default system policies. Currently there is only + * one policy - ManualAuthentication. More may be added later on. + * + * The default policies may be disabled - for example to over-ride + * agent approval for testing the system by setting the following + * property in the config file: + * + * <subsystemId>.Policy.systemPolicies.enable=false + * + * By default the value for this property is true. + * + * Users can over-ride the default system policies by listing their + * 'custom' system policies under the following property: + * + * <subsystemId>.Policy.systemPolicies=<system policy1 class path>, + * <system policy2 class path> + * + * There can only be one instance of the system policy in the system + * and will apply to all requests, and hence predicates are not used + * for a system policy. Due to the same reason, these properties are + * not configurable using the Console. + * + * A System policy may read config properties from a subtree under + * <subsystemId>.Policy.systemPolicies.<ClassName>. An example is + * ra.Policy.systemPolicies.ManualAuthentication.param1=value + */ + private void initSystemPolicies(IConfigStore mConfig) + throws EBaseException { + // If system policies are disabled, return. No Deferral of + // requests may be done. + String enable = mConfig.getString(PROP_DEF_POLICIES + "." + + PROP_ENABLE, "true").trim(); + + if (enable.equalsIgnoreCase("false")) { + mSystemDefaults = DEF_POLICIES; + return; + } + + // Load default policies that are always present. + String configuredDefaults = mConfig.getString(PROP_DEF_POLICIES, + null); + + if (configuredDefaults == null || + configuredDefaults.trim().length() == 0) + mSystemDefaults = DEF_POLICIES; + else { + Vector<String> rules = new Vector<String>(); + StringTokenizer tokenizer = new + StringTokenizer(configuredDefaults.trim(), ","); + + while (tokenizer.hasMoreTokens()) { + String rule = tokenizer.nextToken().trim(); + + rules.addElement(rule); + } + if (rules.size() > 0) { + mSystemDefaults = new String[rules.size()]; + rules.copyInto(mSystemDefaults); + } else + mSystemDefaults = DEF_POLICIES; + } + + // Now Initialize the rules. These defaults have only one + // instance and the rule name is the name of the class itself. + // Any configuration parameters required could be read from + // <subsystemId>.Policy.default.RuleName. + for (int i = 0; i < mSystemDefaults.length; i++) { + // Load the class and make an instance. + // Verify if the class is a valid implementation of + // IPolicyRule + String ruleName = null; + + try { + Object o = Class.forName(mSystemDefaults[i]).newInstance(); + + if (!(o instanceof IEnrollmentPolicy) && + !(o instanceof IRenewalPolicy) && + !(o instanceof IRevocationPolicy) && + !(o instanceof IKeyRecoveryPolicy) && + !(o instanceof IKeyArchivalPolicy)) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_IMPL", + mSystemDefaults[i])); + + IPolicyRule rule = (IPolicyRule) o; + + // Initialize the rule. + ruleName = mSystemDefaults[i].substring( + mSystemDefaults[i].lastIndexOf('.') + 1); + IConfigStore ruleConfig = mConfig.getSubStore( + PROP_DEF_POLICIES + "." + ruleName); + + rule.init(this, ruleConfig); + + // Add the rule to the appropriate PolicySet. + addRule(ruleName, rule); + } catch (EBaseException e) { + throw e; + } catch (Exception e) { + Debug.printStackTrace(e); + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_NO_POLICY_IMPL", + ruleName)); + } + } + } + + /** + * Read list of undeletable policies if any configured in the + * system. + * + * These are required to protect the system from being misconfigured + * to the point that the requests wouldn't serialize or certain + * fields in the certificate(s) being checked will go unchecked + * ..etc. + * + * For now the following policies are undeletable: + * + * DirAuthRule: This is a default DirectoryAuthentication policy + * for user certificates that interprets directory + * credentials. The presence of this policy is needed + * if the OOTB DirectoryAuthentication-based automatic + * certificate issuance is supported. + * + * DefaultUserNameRule: This policy verifies/sets subjectDn for user + * certificates. + * + * DefaultServerNameRule: This policy verifies/sets subjectDn for + * server certificates. + * + * DefaultValidityRule: Verifies/sets validty for all certificates. + * + * DefaultRenewalValidityRule: Verifies/sets validity for certs being + * renewed. + * + * The 'undeletables' cannot be deleted from the config file, nor + * can the be disabled. If any predicates are associated with them + * the predicates can't be changed either. But, other config parameters + * such as maxValidity, renewalInterval ..etc can be changed to suit + * local policy requirements. + * + * During start up the policy processor will verify if the undeletables + * are present, and that they are enabled and that their predicates are + * not changed. + * + * The rules mentioned above are currently hard coded. If these need to + * read from the config file, the 'undeletables' can be configured as + * as follows: + * + * <subsystemId>.Policy.undeletablePolicies=<comma separated rule names> + * Example: + * ra.Policy.undeletablePolicies=DirAuthRule, DefaultUserNameRule, DefaultServerNameRule, DefaultValidityRule, + * DefaultRenewalValidityRule + * + * The predicates if any associated with them may be configured as + * follows: + * <subsystemId>.Policy.undeletablePolicies.DirAuthRule.predicate= certType == client. + * + * where subsystemId is ra or ca. + * + * If the undeletables are configured in the file,the configured entries + * take precedence over the hardcoded ones in this file. If you are + * configuring them in the file, please remember to configure the + * predicates if applicable. + * + * During policy configuration from MCC, the policy processor will not + * let you delete an 'undeletable', nor will it let you disable it. + * You will not be able to change the predicate either. Other parameters + * can be configured as needed. + * + * If a particular rule needs to be removed from the 'undeletables', + * either remove it from the hard coded list above, or configure the + * rules required rules only via the config file. The former needs + * recompilation of the source. The later is flexible to be able to + * make any rule an 'undeletable' or nor an 'undeletable'. + * + * Example: We want to use only manual forms for enrollment. + * We do n't need to burn in DirAuthRule. We need to configure all + * other rules except the DirAuthRule as follows: + * + * ra.Policy.undeletablePolicies = DefaultUserNameRule, DefaultServerNameRule, DefaultValidityRule, + * DefaultRenewalValidityRule + * + * The following predicates are necessary: + * + * ra.Policy.undeletablePolicies.DefaultUserNameRule.predicate = certType == client + * ra.Policy.undeletablePolicies.DefaultServerNameRule.predicate = certType == server + * + * The other two rules do not have any predicates. + */ + private void initUndeletablePolicies(IConfigStore mConfig) + throws EBaseException { + // Read undeletable policies if any configured. + String configuredUndeletables = + mConfig.getString(PROP_UNDELETABLE_POLICIES, null); + + if (configuredUndeletables == null || + configuredUndeletables.trim().length() == 0) { + mUndeletablePolicies = DEF_UNDELETABLE_POLICIES; + return; + } + + Vector<String> rules = new Vector<String>(); + StringTokenizer tokenizer = new + StringTokenizer(configuredUndeletables.trim(), ","); + + while (tokenizer.hasMoreTokens()) { + String rule = tokenizer.nextToken().trim(); + + rules.addElement(rule); + } + + if (rules.size() == 0) { + mUndeletablePolicies = DEF_UNDELETABLE_POLICIES; + return; + } + + // For each rule read from the config file, see if any + // predicate is set. + mUndeletablePolicies = new Hashtable<String, IExpression>(); + for (Enumeration<String> e = rules.elements(); e.hasMoreElements();) { + String urn = (String) e.nextElement(); + + // See if there is predicate in the file + String pred = mConfig.getString(PROP_UNDELETABLE_POLICIES + + "." + urn + "." + PROP_PREDICATE, null); + + IExpression exp = SimpleExpression.NULL_EXPRESSION; + + if (pred != null) + exp = PolicyPredicateParser.parse(pred); + mUndeletablePolicies.put(urn, exp); + } + } + + private void addRule(String ruleName, IPolicyRule rule) { + if (rule instanceof IEnrollmentPolicy) + mEnrollmentRules.addRule(ruleName, rule); + if (rule instanceof IRenewalPolicy) + mRenewalRules.addRule(ruleName, rule); + if (rule instanceof IRevocationPolicy) + mRevocationRules.addRule(ruleName, rule); + if (rule instanceof IKeyRecoveryPolicy) + mKeyRecoveryRules.addRule(ruleName, rule); + if (rule instanceof IKeyArchivalPolicy) + mKeyArchivalRules.addRule(ruleName, rule); + } + + private boolean isSystemDefaultPolicy(String clPath) { + boolean ret = false; + + if (mSystemDefaults == null) + return false; + for (int i = 0; i < mSystemDefaults.length; i++) { + if (clPath.equals(mSystemDefaults[i])) { + ret = true; + break; + } + } + return ret; + } + + private void verifyDefaultPolicyConfig() + throws EPolicyException { + // For each policy in undeletable list make sure that + // the policy is present, is not disabled and its predicate + // is not tampered with. + for (Enumeration<String> e = mUndeletablePolicies.keys(); e.hasMoreElements();) { + String urn = (String) e.nextElement(); + + // See if the rule is in the instance table. + PolicyInstance inst = (PolicyInstance) mInstanceTable.get(urn); + + if (inst == null) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_MISSING_PERSISTENT_RULE", urn)); + + // See if the instance is disabled. + if (!inst.isActive()) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_INACTIVE", urn)); + + // See if the predicated is misconfigured. + IExpression defPred = (IExpression) + mUndeletablePolicies.get(urn); + + // We used SimpleExpression.NULL_EXPRESSION to indicate a null. + if (defPred == SimpleExpression.NULL_EXPRESSION) + defPred = null; + IExpression confPred = inst.getRule().getPredicate(); + + if (defPred == null && confPred != null) { + String[] params = { urn, "null", confPred.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params)); + } else if (defPred != null && confPred == null) { + String[] params = { urn, defPred.toString(), "null" }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params)); + } else if (defPred != null && confPred != null) { + if (!defPred.toString().equals(confPred.toString())) { + String[] params = { urn, defPred.toString(), + confPred.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PERSISTENT_RULE_MISCONFIG", params)); + } + } + } + } +} + +/** + * Class to keep track of various configurable implementations. + */ +class RegisteredPolicy { + String mId; + String mClPath; + + public RegisteredPolicy(String id, String clPath) { + if (id == null || clPath == null) + throw new AssertionException("Policy id or classpath can't be null"); + mId = id; + mClPath = clPath; + } + + public String getClassPath() { + return mClPath; + } + + public String getId() { + return mId; + } +} + +/** + * @deprecated + */ +class PolicyInstance { + String mInstanceId; + String mImplId; + IPolicyRule mRule; + boolean mIsEnabled; + + public PolicyInstance(String instanceId, String implId, + IPolicyRule rule, boolean isEnabled) { + mInstanceId = instanceId; + mImplId = implId; + mRule = rule; + mIsEnabled = isEnabled; + } + + public String getInstanceId() { + return mInstanceId; + } + + public String getImplId() { + return mImplId; + } + + public String getRuleInfo() { + String enabled = mIsEnabled ? "enabled" : "disabled"; + + return mInstanceId + ";" + mImplId + ";visible;" + enabled; + } + + public IPolicyRule getRule() { + return mRule; + } + + public boolean isInstanceOf(String implId) { + return mImplId.equals(implId); + } + + public boolean isActive() { + return mIsEnabled; + } + + public void setActive(boolean stat) { + mIsEnabled = stat; + } + + public void setRule(IPolicyRule newRule) { + mRule = newRule; + } +} diff --git a/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java b/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java new file mode 100644 index 000000000..1fbcf2738 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java @@ -0,0 +1,48 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.policy; + +import com.netscape.certsrv.policy.IPolicyRule; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; + +/** + * + * @deprecated + * + */ +public class JavaScriptRequestProxy { + IRequest req; + + public JavaScriptRequestProxy(IRequest r) { + req = r; + } + + public String getHTTP(String param) { + return req.getExtDataInString(IRequest.HTTP_PARAMS, param); + } + + public String get(String param) { + return req.getExtDataInString(param); + } + + public PolicyResult applyPolicy(IPolicyRule r) { + return r.apply(req); + } + +} diff --git a/base/common/src/com/netscape/cmscore/policy/OrExpression.java b/base/common/src/com/netscape/cmscore/policy/OrExpression.java new file mode 100644 index 000000000..3b220c100 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/OrExpression.java @@ -0,0 +1,67 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.policy; + +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IExpression; +import com.netscape.certsrv.request.IRequest; + +/** + * This class represents an Or expression of the form + * (var1 op val1 OR var2 op val2). + * + * Expressions are used as predicates for policy selection. + * + * @deprecated + * @author kanda + * @version $Revision$, $Date$ + */ +public class OrExpression implements IExpression { + private IExpression mExp1; + private IExpression mExp2; + + public OrExpression(IExpression exp1, IExpression exp2) { + mExp1 = exp1; + mExp2 = exp2; + } + + public boolean evaluate(IRequest req) + throws EPolicyException { + if (mExp1 == null && mExp2 == null) + return true; + else if (mExp1 != null && mExp2 != null) + return mExp1.evaluate(req) || mExp2.evaluate(req); + else if (mExp1 != null && mExp2 == null) + return mExp1.evaluate(req); + else + // (mExp1 == null && mExp2 != null) + return mExp2.evaluate(req); + } + + public String toString() { + if (mExp1 == null && mExp2 == null) + return ""; + else if (mExp1 != null && mExp2 != null) + return mExp1.toString() + " OR " + mExp2.toString(); + else if (mExp1 != null && mExp2 == null) + return mExp1.toString(); + else + // (mExp1 == null && mExp2 != null) + return mExp2.toString(); + } +} diff --git a/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java b/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java new file mode 100644 index 000000000..568a38e6d --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java @@ -0,0 +1,341 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.policy; + +import java.util.Vector; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IExpression; +import com.netscape.cmscore.util.Debug; + +/** + * Default implementation of predicate parser. + * + * Limitations: + * + * 1. Currently parentheses are not suported. + * 2. Only ==, != <, >, <= and >= operators are supported. + * 3. The only boolean operators supported are AND and OR. AND takes precedence + * over OR. Example: a AND b OR e OR c AND d + * is treated as (a AND b) OR e OR (c AND d) + * 4. If this is n't adequate, roll your own. + * + * @deprecated + * @author kanda + * @version $Revision$, $Date$ + */ +public class PolicyPredicateParser { + public static final int OP_AND = 1; + public static final int OP_OR = 2; + public static final int EXPRESSION = 0; + + public static final String AND = "AND"; + public static final String OR = "OR"; + + private static final char COMMA = ','; + + /** + * Parse the predicate expression and return a vector of expressions. + * + * @param predicateExp The predicate expression as read from the config file. + * @return expVector The vector of expressions. + */ + public static IExpression parse(String predicateExpression) + throws EPolicyException { + if (predicateExpression == null || + predicateExpression.length() == 0) + return null; + PredicateTokenizer pt = new PredicateTokenizer(predicateExpression); + + if (pt == null || !pt.hasMoreTokens()) + return null; + + // The first token cannot be an operator. We are not dealing with + // reverse-polish notation. + String token = pt.nextToken(); + + if (getOP(token) != EXPRESSION) { + if (Debug.ON) + Debug.trace("Malformed expression: " + predicateExpression); + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_BAD_POLICY_EXPRESSION", predicateExpression)); + } + IExpression current = parseExpression(token); + boolean malformed = false; + Vector<IExpression> expSet = new Vector<IExpression>(); + int prevType = EXPRESSION; + + while (pt.hasMoreTokens()) { + token = pt.nextToken(); + int curType = getOP(token); + + if ((prevType != EXPRESSION && curType != EXPRESSION) || + (prevType == EXPRESSION && curType == EXPRESSION)) { + malformed = true; + break; + } + + // If an operator seen skip to the next token + if (curType != EXPRESSION) { + prevType = curType; + continue; + } + + // If the previous type was an OR token, add the current expression to + // the expression set; + if (prevType == OP_OR) { + expSet.addElement(current); + current = parseExpression(token); + prevType = curType; + continue; + } + + // If the previous type was an AND token, make an AND expression + if (prevType == OP_AND) { + current = new AndExpression(current, parseExpression(token)); + prevType = curType; + } + } + if (malformed) { + if (Debug.ON) + Debug.trace("Malformed expression: " + predicateExpression); + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_BAD_POLICY_EXPRESSION", + predicateExpression)); + } + + // Form an ORExpression + if (current != null) + expSet.addElement(current); + + int size = expSet.size(); + + if (size == 0) + return null; + OrExpression orExp = new + OrExpression((IExpression) expSet.elementAt(0), null); + + for (int i = 1; i < size; i++) + orExp = new OrExpression(orExp, + (IExpression) expSet.elementAt(i)); + return orExp; + } + + private static int getOP(String token) { + if (token.equalsIgnoreCase(AND)) + return OP_AND; + else if (token.equalsIgnoreCase(OR)) + return OP_OR; + else + return EXPRESSION; + } + + private static IExpression parseExpression(String input) + throws EPolicyException { + // If the expression has multiple parts separated by commas + // we need to construct an AND expression. Else we will return a + // simple expression. + int commaIndex = input.indexOf(COMMA); + + if (commaIndex < 0) + return SimpleExpression.parse(input); + int currentIndex = 0; + Vector<SimpleExpression> expVector = new Vector<SimpleExpression>(); + + while (commaIndex > 0) { + SimpleExpression exp = (SimpleExpression) + SimpleExpression.parse(input.substring(currentIndex, + commaIndex)); + + expVector.addElement(exp); + currentIndex = commaIndex + 1; + commaIndex = input.indexOf(COMMA, currentIndex); + } + if (currentIndex < (input.length() - 1)) { + SimpleExpression exp = (SimpleExpression) + SimpleExpression.parse(input.substring(currentIndex)); + + expVector.addElement(exp); + } + + int size = expVector.size(); + SimpleExpression exp1 = (SimpleExpression) expVector.elementAt(0); + SimpleExpression exp2 = (SimpleExpression) expVector.elementAt(1); + AndExpression andExp = new AndExpression(exp1, exp2); + + for (int i = 2; i < size; i++) { + andExp = new AndExpression(andExp, (SimpleExpression) expVector.elementAt(i)); + } + return andExp; + } + + public static void main(String[] args) { + + /********* + * IRequest req = new IRequest(); + * try + * { + * req.set("ou", "people"); + * req.set("cn", "John Doe"); + * req.set("uid", "jdoes"); + * req.set("o", "airius.com"); + * req.set("certtype", "client"); + * req.set("request", "issuance"); + * req.set("id", new Integer(10)); + * req.set("dualcerts", new Boolean(true)); + * + * Vector v = new Vector(); + * v.addElement("one"); + * v.addElement("two"); + * v.addElement("three"); + * req.set("count", v); + * } + * catch (Exception e){e.printStackTrace();} + * String[] array = { "ou == people AND certtype == client", + * "ou == servergroup AND certtype == server", + * "uid == jdoes, ou==people, o==airius.com OR ou == people AND certType == client OR certType == server AND cn == needles.mcom.com" + * , + * }; + * for (int i = 0; i < array.length; i++) + * { + * System.out.println(); + * System.out.println("String: " + array[i]); + * IExpression exp = null; + * try + * { + * exp = parse(array[i]); + * if (exp != null) + * { + * System.out.println("Parsed Expression: " + exp); + * boolean result = exp.evaluate(req); + * System.out.println("Result: " + result); + * } + * } + * catch (Exception e) {e.printStackTrace(); } + * } + * + * + * try + * { + * BufferedReader rdr = new BufferedReader( + * new FileReader(args[0])); + * String line; + * while((line=rdr.readLine()) != null) + * { + * System.out.println(); + * System.out.println("Line Read: " + line); + * IExpression exp = null; + * try + * { + * exp = parse(line); + * if (exp != null) + * { + * System.out.println(exp); + * boolean result = exp.evaluate(req); + * System.out.println("Result: " + result); + * } + * + * }catch (Exception e){e.printStackTrace();} + * } + * } + * catch (Exception e){e.printStackTrace(); } + *******/ + } + +} + +class PredicateTokenizer { + String input; + int currentIndex; + int endOfString; + String nextToken; + boolean first; + + public PredicateTokenizer(String predString) { + input = predString; + currentIndex = 0; + nextToken = null; + } + + public boolean hasMoreTokens() { + return (currentIndex != -1); + } + + public String nextToken() { + if (nextToken != null) { + String toReturn = nextToken; + + nextToken = null; + return toReturn; + } + + int andIndex = input.indexOf(" AND", currentIndex); + + if (andIndex < 0) + andIndex = input.indexOf(" and", currentIndex); + int orIndex = input.indexOf(" OR", currentIndex); + + if (orIndex < 0) + orIndex = input.indexOf(" or", currentIndex); + String toReturn = null; + + if (andIndex == -1 && orIndex == -1) { + if (currentIndex == 0) { + currentIndex = -1; + toReturn = input; + } else { + int temp = currentIndex; + + currentIndex = -1; + toReturn = input.substring(temp); + } + } else if (andIndex >= 0 && (andIndex < orIndex || orIndex == -1)) { + if (currentIndex != andIndex) { + toReturn = input.substring(currentIndex, andIndex); + nextToken = input.substring(andIndex + 1, andIndex + 4); + currentIndex = andIndex + 4; + } else { + toReturn = "AND"; + currentIndex += 4; + } + } else if (orIndex >= 0 && (orIndex < andIndex || andIndex == -1)) { + if (currentIndex != orIndex) { + toReturn = input.substring(currentIndex, orIndex); + nextToken = input.substring(orIndex + 1, orIndex + 3); + currentIndex = orIndex + 3; + } else { + toReturn = "OR"; + currentIndex += 3; + } + } else { + // Cannot happen; Assert here. + toReturn = null; + System.out.println("We shouldn't be here!"); + } + if (toReturn == null) + return null; + else { + String trimmed = toReturn.trim(); + + if (trimmed == null || trimmed.length() == 0) + return nextToken(); + else + return trimmed; + } + } +} diff --git a/base/common/src/com/netscape/cmscore/policy/PolicySet.java b/base/common/src/com/netscape/cmscore/policy/PolicySet.java new file mode 100644 index 000000000..9e7ecdc64 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/PolicySet.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.cmscore.policy; + +import java.util.Enumeration; +import java.util.Vector; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.IExpression; +import com.netscape.certsrv.policy.IPolicyRule; +import com.netscape.certsrv.policy.IPolicySet; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cmscore.util.Debug; + +/** + * Implements a policy set per IPolicySet interface. This class + * uses a vector of ordered policies to enforce priority. + * + * @deprecated + * @author kanda + * @version $Revision$, $Date$ + */ +public class PolicySet implements IPolicySet { + private String mName; + private Vector<String> mRuleNames = new Vector<String>(); + private Vector<IPolicyRule> mRules = new Vector<IPolicyRule>(); + private ILogger mLogger = CMS.getLogger(); + + public PolicySet(String name) { + mName = name; + } + + /** + * Returns the name of the rule set. + * <P> + * + * @return The name of the rule set. + */ + public String getName() { + return mName; + } + + /** + * Returns the no of rules in a set. + * <P> + * + * @return the no of rules. + */ + public int count() { + return mRules.size(); + } + + /** + * Add a policy rule. + * <P> + * + * @param ruleName The name of the rule to be added. + * @param rule The rule to be added. + */ + public void addRule(String ruleName, IPolicyRule rule) { + if (mRuleNames.indexOf(ruleName) >= 0) + return; // XXX - Duplicate - Need to throw an exception. + + if (ruleName != null && rule != null) { + mRuleNames.addElement(ruleName); + mRules.addElement(rule); + } + // XXX - TODO: else throw an exception. + + } + + /** + * Remplaces a policy rule identified by the given name. + * + * @param name The name of the rule to be replaced. + * @param rule The rule to be replaced. + */ + public void replaceRule(String ruleName, IPolicyRule rule) { + int index = mRuleNames.indexOf(ruleName); + + if (index < 0) { + addRule(ruleName, rule); + return; + } + + mRuleNames.setElementAt(ruleName, index); + mRules.setElementAt(rule, index); + } + + /** + * Removes a policy rule identified by the given name. + * + * @param name The name of the rule to be removed. + */ + public void removeRule(String ruleName) { + int index = mRuleNames.indexOf(ruleName); + + if (index < 0) + return; // XXX - throw an exception. + + mRuleNames.removeElementAt(index); + mRules.removeElementAt(index); + } + + /** + * Returns the rule identified by a given name. + * <P> + * + * @param name The name of the rule to be return. + * @return The rule identified by the given name or null if none exists. + */ + public IPolicyRule getRule(String ruleName) { + int index = mRuleNames.indexOf(ruleName); + + if (index < 0) + return null; + return (IPolicyRule) mRules.elementAt(index); + } + + /** + * Returns an enumeration of rules. + * <P> + * + * @return An enumeration of rules. + */ + public Enumeration<IPolicyRule> getRules() { + return mRules.elements(); + } + + /** + * Apply policies on a given request from a rule set. + * The rules may modify the request. + * + * @param req The request to apply policies on. + * @return the PolicyResult. + */ + public PolicyResult apply(IRequest req) { + // If there are no rules, we are done. + + if (mRules.size() == 0) + return PolicyResult.ACCEPTED; + + // All policies are applied before returning the result. Hence + // if atleast one of the policies returns a REJECTED, we need to + // return that status. If none of the policies REJECTED + // the request, but atleast one of them DEFERRED the request, we + // need to return DEFERRED. + boolean rejected = false; + boolean deferred = false; + int size = mRules.size(); + + for (int index = 0; index < size; index++) { + String name = (String) mRuleNames.elementAt(index); + IPolicyRule rule = (IPolicyRule) mRules.elementAt(index); + IExpression exp = rule.getPredicate(); + + try { + if (Debug.ON) + Debug.trace("evaluating predicate for rule " + rule.getName()); + CMS.debug("PolicySet: apply()- evaluating predicate for rule " + rule.getName()); + if (exp != null && !exp.evaluate(req)) + continue; + } catch (Exception e) { + e.printStackTrace(); + } + + if (!typeMatched(rule, req)) + continue; + + try { + if (Debug.ON) + Debug.trace("Policy " + name + " selected"); + CMS.debug("Policy " + name + " selected"); + PolicyResult result = rule.apply(req); + CMS.debug("Policy applied"); + + if (Debug.ON) + Debug.trace("Policy " + name + " returned " + result); + + if (result == PolicyResult.REJECTED) { + // It is hard to find out the owner at the moment unless + // we pass that info down the chain. For now use S_OTHER + // as the system id for the log entry. + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_POLICY_REJECT_RESULT", req.getRequestId().toString(), name)); + rejected = true; + } else if (result == PolicyResult.DEFERRED) { + // It is hard to find out the owner at the moment unless + // we pass that info down the chain. For now use S_OTHER + // as the system id for the log entry. + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_WARN, + CMS.getLogMessage("CMSCORE_POLICY_DEFER_RESULT", req.getRequestId().toString(), name)); + deferred = true; + } else if (result == PolicyResult.ACCEPTED) { + // It is hard to find out the owner at the moment unless + // we pass that info down the chain. For now use S_OTHER + // as the system id for the log entry. + } else { + // should not get to this status + // It is hard to find out the owner at the moment unless + // we pass that info down the chain. For now use S_OTHER + // as the system id for the log entry. + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_INFO, + "policy: Request " + req.getRequestId() + " - Result of applying rule: " + name + + " is: " + getPolicyResult(result)); + } + } catch (Throwable ex) { + // Customer can install his own policies. + // The policy may have bug. We want to + // catch those problems and report + // them to the log + mLogger.log( + ILogger.EV_SYSTEM, + ILogger.S_OTHER, + ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_POLICY_ERROR_RESULT", req.getRequestId().toString(), name, + ex.toString())); + // treat as rejected to prevent request from going into + // a weird state. request queue doesn't handle this case. + rejected = true; + ((IPolicyRule) rule).setError( + req, + CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", rule.getName(), ex.toString()), null); + } + } + + if (rejected) { + return PolicyResult.REJECTED; + } else if (deferred) { + return PolicyResult.DEFERRED; + } else { + mLogger.log(ILogger.EV_SYSTEM, ILogger.S_OTHER, + ILogger.LL_INFO, + "Request " + req.getRequestId() + + " Policy result: successful"); + return PolicyResult.ACCEPTED; + } + } + + public void printPolicies() { + if (mRules.size() == 0) + return; + System.out.println("Policy Set Name: " + mName); + System.out.println(); + int size = mRules.size(); + + for (int index = 0; index < size; index++) { + String ruleName = (String) mRuleNames.elementAt(index); + + System.out.println("Rule Name: " + ruleName); + System.out.println("Implementation: " + + mRules.elementAt(index).getClass().getName()); + } + } + + String getPolicyResult(PolicyResult res) { + if (res == PolicyResult.ACCEPTED) + return "accepted"; + else if (res == PolicyResult.DEFERRED) + return "deferred"; + else if (res == PolicyResult.REJECTED) + return "rejected"; + else + return "unknown"; + } + + boolean typeMatched(IPolicyRule rule, IRequest req) { + + if (req.getExtDataInCertInfoArray(IRequest.CERT_INFO) != null) { + return true; + } + + if (req.getExtDataInCertArray(IRequest.OLD_CERTS) != null) { + return true; + } + + return false; + } +} diff --git a/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java b/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java new file mode 100644 index 000000000..892fd6451 --- /dev/null +++ b/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java @@ -0,0 +1,434 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.policy; + +import java.util.Enumeration; +import java.util.Vector; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IExpression; +import com.netscape.certsrv.request.IRequest; +import com.netscape.cmscore.util.AssertionException; +import com.netscape.cmscore.util.Debug; + +/** + * This class represents an expression of the form var = val, + * var != val, var < val, var > val, var <= val, var >= val. + * + * Expressions are used as predicates for policy selection. + * + * @deprecated + * @author kanda + * @version $Revision$, $Date$ + */ +public class SimpleExpression implements IExpression { + private String mPfx; + private String mVar; + private String mVal; + private String mPartialMatch; + private int mOp; + private boolean hasWildCard; + public static final char WILDCARD_CHAR = '*'; + + // This is just for indicating a null expression. + public static SimpleExpression NULL_EXPRESSION = new SimpleExpression("null", OP_EQUAL, "null"); + + public static IExpression parse(String input) + throws EPolicyException { + // Get the index of operator + // Debug.trace("SimpleExpression::input: " + input); + String var = null; + int op = -1; + String val = null; + + // XXX - Kanda - Need to change this parsing code eventually. + ExpressionComps comps = parseForEquality(input); + + if (comps == null) + comps = parseForInEquality(input); + if (comps == null) + comps = parseForGE(input); + if (comps == null) + comps = parseForLE(input); + if (comps == null) + comps = parseForGT(input); + if (comps == null) + comps = parseForLT(input); + if (comps == null) + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_BAD_POLICY_EXPRESSION", input)); + String pfx = null; + String rawVar = comps.getAttr(); + int dotIdx = rawVar.indexOf('.'); + + if (dotIdx != -1) { + pfx = rawVar.substring(0, dotIdx).trim(); + var = rawVar.substring(dotIdx + 1).trim(); + } else { + var = rawVar; + } + op = comps.getOp(); + val = comps.getVal(); + return new SimpleExpression(pfx, var, op, val); + } + + public SimpleExpression(String var, int op, String val) { + this(null, var, op, val); + } + + public SimpleExpression(String prefix, String var, int op, String val) { + // Assert that op has to be either IExpression.OP_EQUAL or + // IExpression.OP_NEQUAL. + // If val or var is null throw an exception! + mPfx = prefix; + mVar = var; + mOp = op; + mVal = val; + int firstIndex; + + if ((firstIndex = mVal.indexOf(WILDCARD_CHAR)) >= 0) { + hasWildCard = true; + int nextIndex = mVal.indexOf(WILDCARD_CHAR, firstIndex + 1); + + if (nextIndex == -1) { + if (firstIndex == 0) + mPartialMatch = mVal.substring(1); + else + mPartialMatch = mVal.substring(0, firstIndex); + } else + mPartialMatch = mVal.substring(firstIndex + 1, nextIndex); + } else + hasWildCard = false; + } + + public boolean evaluate(IRequest req) + throws EPolicyException { + // mPfx and mVar are looked up case-indendently + String givenVal = req.getExtDataInString(mPfx, mVar); + + if (Debug.ON) + Debug.trace("mPfx: " + mPfx + " mVar: " + mVar + + ",Given Value: " + givenVal + ", Value to compare with: " + mVal); + + return matchValue(givenVal); + } + + private boolean matchVector(Vector<?> value) + throws EPolicyException { + boolean result = false; + Enumeration<?> e = (Enumeration<?>) value.elements(); + + for (; e.hasMoreElements();) { + result = matchValue(e.nextElement()); + if (result) + break; + } + return result; + } + + private boolean matchStringArray(String[] value) + throws EPolicyException { + boolean result = false; + + for (int i = 0; i < value.length; i++) { + result = matchValue((Object) value[i]); + if (result) + break; + } + return result; + } + + private boolean matchValue(Object value) + throws EPolicyException { + boolean result; + + // There is nothing to compare with! + if (value == null) + return false; + + // XXX - Kanda: We need a better way of handling this!. + if (value instanceof String) + result = matchStringValue((String) value); + else if (value instanceof Integer) + result = matchIntegerValue((Integer) value); + else if (value instanceof Boolean) + result = matchBooleanValue((Boolean) value); + else if (value instanceof Vector) + result = matchVector((Vector<?>) value); + else if (value instanceof String[]) + result = matchStringArray((String[]) value); + else + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_ATTR_VALUE", + value.getClass().getName())); + return result; + } + + private boolean matchStringValue(String givenVal) + throws EPolicyException { + boolean result; + + switch (mOp) { + case OP_EQUAL: + if (hasWildCard) + result = (givenVal.indexOf(mPartialMatch) >= 0); + else + result = givenVal.equalsIgnoreCase(mVal); + break; + + case OP_NEQUAL: + if (hasWildCard) + result = (givenVal.indexOf(mPartialMatch) < 0); + else + result = !givenVal.equalsIgnoreCase(mVal); + break; + + case OP_LT: + result = (givenVal.compareTo(mVal) < 0); + break; + + case OP_GT: + result = (givenVal.compareTo(mVal) > 0); + break; + + case OP_GE: + result = (givenVal.compareTo(mVal) >= 0); + break; + + case OP_LE: + result = (givenVal.compareTo(mVal) >= 0); + break; + + default: + throw new AssertionException("Invalid operation code"); + } + return result; + } + + private boolean matchIntegerValue(Integer intVal) + throws EPolicyException { + boolean result; + int storedVal; + int givenVal = intVal.intValue(); + + try { + storedVal = new Integer(mVal).intValue(); + } catch (Exception e) { + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_ATTR_VALUE", mVal)); + + } + switch (mOp) { + case OP_EQUAL: + result = (givenVal == storedVal); + break; + + case OP_NEQUAL: + result = (givenVal != storedVal); + break; + + case OP_LT: + result = (givenVal < storedVal); + break; + + case OP_GT: + result = (givenVal > storedVal); + break; + + case OP_GE: + result = (givenVal >= storedVal); + break; + + case OP_LE: + result = (givenVal >= storedVal); + break; + + default: + throw new AssertionException("Invalid operation code"); + } + return result; + } + + private boolean matchBooleanValue(Boolean givenVal) + throws EPolicyException { + boolean result; + Boolean storedVal; + + if (!(mVal.equalsIgnoreCase("true") || mVal.equalsIgnoreCase("false"))) + throw new EPolicyException(CMS.getUserMessage("CMS_POLICY_INVALID_ATTR_VALUE", + mVal)); + storedVal = new Boolean(mVal); + switch (mOp) { + case OP_EQUAL: + result = (givenVal.equals(storedVal)); + break; + + case OP_NEQUAL: + case OP_LT: + case OP_GT: + case OP_GE: + case OP_LE: + result = (!givenVal.equals(storedVal)); + break; + + default: + throw new AssertionException("Invalid operation code"); + } + return result; + } + + public String toString() { + String op = null; + + switch (mOp) { + case IExpression.OP_EQUAL: + op = IExpression.EQUAL_STR; + break; + + case IExpression.OP_NEQUAL: + op = IExpression.NEQUAL_STR; + break; + + case IExpression.OP_GT: + op = IExpression.GT_STR; + break; + + case IExpression.OP_LT: + op = IExpression.LT_STR; + break; + + case IExpression.OP_GE: + op = IExpression.GE_STR; + break; + + case IExpression.OP_LE: + op = IExpression.LE_STR; + break; + } + if (mPfx != null && mPfx.length() > 0) + return mPfx + "." + mVar + " " + op + " " + mVal; + else + return mVar + " " + op + " " + mVal; + } + + private static ExpressionComps parseForEquality(String expression) { + int index = expression.indexOf(IExpression.EQUAL_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_EQUAL; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForInEquality(String expression) { + int index = expression.indexOf(IExpression.NEQUAL_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_NEQUAL; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForGT(String expression) { + int index = expression.indexOf(IExpression.GT_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_GT; + String val = expression.substring(index + 1).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForLT(String expression) { + int index = expression.indexOf(IExpression.LT_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_LT; + String val = expression.substring(index + 1).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForGE(String expression) { + int index = expression.indexOf(IExpression.GE_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_GE; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForLE(String expression) { + int index = expression.indexOf(IExpression.LE_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_LE; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } +} + +class ExpressionComps { + String attr; + int op; + String val; + + public ExpressionComps(String a, int o, String v) { + attr = a; + op = o; + val = v; + } + + public String getAttr() { + return attr; + } + + public int getOp() { + return op; + } + + public String getVal() { + return val; + } +} |