summaryrefslogtreecommitdiffstats
path: root/pki/base/common/src/com/netscape/cmscore/policy
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore/policy')
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/AndExpression.java59
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java672
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java1552
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java46
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java65
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java373
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/PolicySet.java301
-rw-r--r--pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java435
8 files changed, 3503 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cmscore/policy/AndExpression.java b/pki/base/common/src/com/netscape/cmscore/policy/AndExpression.java
new file mode 100644
index 000000000..fb3134ffa
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/AndExpression.java
@@ -0,0 +1,59 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.base.*;
+import com.netscape.certsrv.policy.*;
+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.
+ *
+ * @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/pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java b/pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java
new file mode 100644
index 000000000..7a8ab4342
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/GeneralNameUtil.java
@@ -0,0 +1,672 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+
+import java.util.*;
+import java.io.*;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import netscape.security.x509.*;
+import netscape.security.util.*;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.cmscore.util.Debug;
+
+
+/**
+ * Class that can be used to form general names from configuration file.
+ * Used by policies and extension commands.
+ */
+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 = com.netscape.osutil.OSUtil.AtoB(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 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 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 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 formGeneralNames(Object value)
+ throws EBaseException {
+ Vector gns = new Vector();
+ 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 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 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 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 params) {
+ params.addElement(mNameDot + PROP_REQUEST_ATTR + "=" + mRequestAttr);
+ super.getInstanceParams(params);
+ }
+
+ public static void getDefaultParams(String name, Vector 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 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/pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java b/pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java
new file mode 100644
index 000000000..63b28d995
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/GenericPolicyProcessor.java
@@ -0,0 +1,1552 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import java.text.*;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.request.IPolicy;
+import com.netscape.certsrv.request.PolicyResult;
+import com.netscape.certsrv.apps.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.certsrv.authority.*;
+import com.netscape.certsrv.common.*;
+import com.netscape.certsrv.logging.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.cmscore.base.*;
+import com.netscape.certsrv.base.IConfigStore;
+import com.netscape.cmscore.util.*;
+import com.netscape.cmscore.request.ARequestQueue;
+
+
+/**
+ * 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.
+ *
+ * @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 DEF_UNDELETABLE_POLICIES =
+ new Hashtable();
+
+ private String mId = "Policy";
+ private Vector mPolicyOrder = new Vector();
+ private Hashtable mImplTable = new Hashtable();
+ private Hashtable mInstanceTable = new Hashtable();
+ 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 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 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";
+ }
+
+ private void setError(IRequest req, String format, String arg) {
+ if (format == null)
+ return;
+ EPolicyException ex = new EPolicyException(format, arg);
+
+ Vector ev = req.getExtDataInStringVector(IRequest.ERRORS);
+ if (ev == null) {
+ ev = new Vector();
+ }
+ ev.addElement(ex.toString());
+ req.setExtData(IRequest.ERRORS, ev);
+ }
+
+ public Enumeration getPolicyImpls() {
+ Vector impls = new Vector();
+ Enumeration enum1 = mImplTable.elements();
+ Enumeration 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 getPolicyImplsInfo() {
+ Vector impls = new Vector();
+ Enumeration enum1 = mImplTable.elements();
+ Enumeration 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 getPolicyImplConfig(String id) {
+ IPolicyRule rp = getPolicyImpl(id);
+
+ if (rp == null)
+ return null;
+ Vector v = rp.getDefaultParams();
+
+ if (v == null)
+ v = new Vector();
+ 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 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 getPolicyInstances() {
+ Vector rules = new Vector();
+ Enumeration enum1 = mPolicyOrder.elements();
+ Enumeration 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 getPolicyInstancesInfo() {
+ Vector rules = new Vector();
+ Enumeration enum1 = mPolicyOrder.elements();
+ Enumeration ret = null;
+
+ try {
+ while (enum1.hasMoreElements()) {
+ String ruleName = (String) enum1.nextElement();
+ PolicyInstance instance =
+ (PolicyInstance) 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 getPolicyInstanceConfig(String id) {
+ PolicyInstance policyInstance = (PolicyInstance)
+ mInstanceTable.get(id);
+
+ if (policyInstance == null)
+ return null;
+ Vector v = policyInstance.getRule().getInstanceParams();
+
+ if (v == null)
+ v = new Vector();
+ 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 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 keys = ht.keys(); keys.hasMoreElements();) {
+ String key = (String) keys.nextElement();
+ String val = (String) 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 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 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 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 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 policyOrder = new Vector();
+ 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 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 v1, Vector 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 rules) {
+ StringBuffer sb = new StringBuffer();
+
+ for (Enumeration 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 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 rules = new Vector();
+ 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 rules = new Vector();
+ 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();
+ for (Enumeration 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 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;
+ }
+}
+
+
+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/pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java b/pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java
new file mode 100644
index 000000000..3f421fca4
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/JavaScriptRequestProxy.java
@@ -0,0 +1,46 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+
+import com.netscape.certsrv.request.*;
+import com.netscape.certsrv.policy.*;
+
+import com.netscape.cmscore.util.Debug;
+
+
+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/pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java b/pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java
new file mode 100644
index 000000000..dfbcb0ef6
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/OrExpression.java
@@ -0,0 +1,65 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+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.
+ *
+ * @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/pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java b/pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java
new file mode 100644
index 000000000..46a874291
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/PolicyPredicateParser.java
@@ -0,0 +1,373 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2007 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cmscore.policy;
+
+
+import java.util.*;
+import java.io.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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.
+ *
+ * @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();
+ boolean opANDSeen;
+ boolean opORSeen;
+
+ 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 expSet = new Vector();
+ 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 expVector = new Vector();
+
+ 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;
+ }
+ }
+}
+
+
+class AttributeSet implements IAttrSet {
+ Hashtable ht = new Hashtable();
+ public AttributeSet() {
+ }
+
+ public void delete(String name)
+ throws EBaseException {
+ Object ob = ht.get(name);
+
+ ht.remove(ob);
+ }
+
+ public Object get(String name)
+ throws EBaseException {
+ return ht.get(name);
+ }
+
+ public void set(String name, Object ob)
+ throws EBaseException {
+ ht.put(name, ob);
+ }
+
+ public Enumeration getElements() {
+ return ht.elements();
+ }
+}
diff --git a/pki/base/common/src/com/netscape/cmscore/policy/PolicySet.java b/pki/base/common/src/com/netscape/cmscore/policy/PolicySet.java
new file mode 100644
index 000000000..6ec1fa5c2
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/PolicySet.java
@@ -0,0 +1,301 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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 netscape.security.x509.X509CertImpl;
+import netscape.security.x509.X509CertInfo;
+
+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.
+ *
+ * @author kanda
+ * @version $Revision$, $Date$
+ */
+public class PolicySet implements IPolicySet {
+ private String mName;
+ private Vector mRuleNames = new Vector();
+ private Vector mRules = new Vector();
+ 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 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.
+ int cnt;
+
+ if ((cnt = 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/pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java b/pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java
new file mode 100644
index 000000000..7b771442c
--- /dev/null
+++ b/pki/base/common/src/com/netscape/cmscore/policy/SimpleExpression.java
@@ -0,0 +1,435 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 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.*;
+import com.netscape.certsrv.base.*;
+import com.netscape.certsrv.policy.*;
+import com.netscape.cmscore.util.*;
+import com.netscape.certsrv.request.IRequest;
+import com.netscape.certsrv.apps.CMS;
+
+
+/**
+ * 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.
+ *
+ * @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;
+ }
+}
+