diff options
Diffstat (limited to 'pki/base/common/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java')
-rw-r--r-- | pki/base/common/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java | 434 |
1 files changed, 434 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java b/pki/base/common/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java new file mode 100644 index 000000000..be065245a --- /dev/null +++ b/pki/base/common/src/com/netscape/cms/policy/extensions/SubjectDirectoryAttributesExt.java @@ -0,0 +1,434 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.extensions; + + +import java.util.*; +import java.io.*; +import java.security.cert.*; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.certsrv.policy.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authentication.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.extensions.*; +import com.netscape.certsrv.apps.*; +import netscape.security.x509.*; +import netscape.security.util.*; +import netscape.ldap.*; +import com.netscape.cms.policy.APolicyRule; + + +/** + * Policy to add the subject directory attributes extension. + * <P> + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class SubjectDirectoryAttributesExt extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + protected static final String PROP_CRITICAL = "critical"; + protected static final String PROP_ATTRIBUTE = "attribute"; + protected static final String PROP_NUM_ATTRIBUTES = "numAttributes"; + + protected static final boolean DEF_CRITICAL = false; + protected static final int DEF_NUM_ATTRIBUTES = 3; + protected static final int MAX_NUM_ATTRIBUTES = 10; + + protected boolean mCritical; + protected int mNumAttributes; + protected AttributeConfig[] mAttributes = null; + + protected IConfigStore mConfig; + protected SubjectDirAttributesExtension mExt = null; + + protected Vector mParams = new Vector(); + private String[] mEPI = null; // extended plugin info + protected static Vector mDefParams = new Vector(); + + static { + setDefaultParams(); + } + + public SubjectDirectoryAttributesExt() { + NAME = "SubjectDirectoryAttributesExtPolicy"; + DESC = "Sets Subject Directory Attributes Extension in certificates."; + setExtendedPluginInfo(); + } + + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + boolean enabled = config.getBoolean("enabled", false); + + mConfig = config; + + mCritical = mConfig.getBoolean(PROP_CRITICAL, false); + mNumAttributes = mConfig.getInteger(PROP_NUM_ATTRIBUTES, DEF_NUM_ATTRIBUTES); + if (mNumAttributes < 1) { + EBaseException ex = new EBaseException( + CMS.getUserMessage("CMS_BASE_MUST_BE_POSITIVE_NUMBER", PROP_NUM_ATTRIBUTES)); + + log(ILogger.LL_FAILURE, NAME + " Error: " + ex.toString()); + throw ex; + } + mAttributes = new AttributeConfig[mNumAttributes]; + for (int i = 0; i < mNumAttributes; i++) { + String name = PROP_ATTRIBUTE + i; + IConfigStore c = mConfig.getSubStore(name); + + mAttributes[i] = new AttributeConfig(name, c, enabled); + } + if (enabled) { + try { + mExt = formExt(null); + } catch (IOException e) { + log(ILogger.LL_FAILURE, NAME + " Error: " + e.getMessage()); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", + "Error forming Subject Directory Attributes Extension. " + + "See log file for details.")); + } + } + setInstanceParams(); + } + + public PolicyResult apply(IRequest req) { + PolicyResult res = PolicyResult.ACCEPTED; + X509CertInfo[] ci = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + if (ci == null || ci[0] == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO"), NAME); + return PolicyResult.REJECTED; // unrecoverable error. + } + + for (int i = 0; i < ci.length; i++) { + PolicyResult r = applyCert(req, ci[i]); + + if (r == PolicyResult.REJECTED) + return r; + } + return PolicyResult.ACCEPTED; + } + + public PolicyResult applyCert(IRequest req, X509CertInfo certInfo) { + CertificateExtensions extensions = null; + SubjectDirAttributesExtension subjDirExt = null; + + try { + // get extension and remove if exists. + extensions = (CertificateExtensions) + certInfo.get(X509CertInfo.EXTENSIONS); + if (extensions == null) { + extensions = new CertificateExtensions(); + certInfo.set(X509CertInfo.VERSION, + new CertificateVersion(CertificateVersion.V3)); + certInfo.set(X509CertInfo.EXTENSIONS, extensions); + } else { + try { + extensions.delete(SubjectDirAttributesExtension.NAME); + } catch (IOException ee) { + // if name is not found, try deleting the extension using the OID + try { + extensions.delete("2.5.29.9"); + } catch (IOException eee) { + } + } + } + + // form extension and set. + if (mExt != null) { + extensions.set(SubjectDirAttributesExtension.NAME, mExt); + } else { + SubjectDirAttributesExtension ext = formExt(req); + + if (ext != null) + extensions.set(SubjectDirAttributesExtension.NAME, formExt(req)); + } + return PolicyResult.ACCEPTED; + } catch (CertificateException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CERT_INFO_ERROR", e.getMessage())); + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), + NAME, "Certificate Info Error"); + return PolicyResult.REJECTED; // unrecoverable error. + } catch (IOException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("BASE_IO_ERROR", e.getMessage())); + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR"), + NAME, "IOException Error"); + return PolicyResult.REJECTED; + } + } + + private Vector formValues(String val) { + StringTokenizer tokenizer = new StringTokenizer(val, "+"); + Vector v = new Vector(); + + while (tokenizer.hasMoreElements()) { + String s = (String) tokenizer.nextElement(); + + v.addElement(s); + } + return v; + } + + public Vector getInstanceParams() { + return mParams; // inited in init() + } + + public Vector getDefaultParams() { + return mDefParams; + } + + public String[] getExtendedPluginInfo(Locale locale) { + return mEPI; // inited in the constructor. + } + + private void setInstanceParams() { + mParams.addElement(PROP_CRITICAL + "=" + mCritical); + mParams.addElement(PROP_NUM_ATTRIBUTES + "=" + mNumAttributes); + for (int i = 0; i < mNumAttributes; i++) { + mAttributes[i].getInstanceParams(mParams); + } + // clean up others if exists. expensive. + for (int j = mNumAttributes; j < MAX_NUM_ATTRIBUTES; j++) { + mConfig.removeSubStore(PROP_ATTRIBUTE + j); + } + } + + private static void setDefaultParams() { + mDefParams.addElement(PROP_CRITICAL + "=" + DEF_CRITICAL); + mDefParams.addElement(PROP_NUM_ATTRIBUTES + "=" + DEF_NUM_ATTRIBUTES); + for (int i = 0; i < DEF_NUM_ATTRIBUTES; i++) { + AttributeConfig.getDefaultParams(PROP_ATTRIBUTE + i, mDefParams); + } + } + + private void setExtendedPluginInfo() { + Vector v = new Vector(); + + v.addElement(PROP_CRITICAL + ";boolean;" + + "RFC 2459 recommendation: MUST be non-critical."); + v.addElement(PROP_NUM_ATTRIBUTES + ";number;" + + "Number of Attributes in the extension."); + + for (int i = 0; i < MAX_NUM_ATTRIBUTES; i++) { + AttributeConfig.getExtendedPluginInfo(PROP_ATTRIBUTE + i, v); + } + + v.addElement(IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-subjectdirectoryattributes"); + v.addElement(IExtendedPluginInfo.HELP_TEXT + + ";Adds Subject Directory Attributes extension. See RFC 2459 (4.2.1.9). It's not recommended as an essential part of the profile, but may be used in local environments."); + + mEPI = com.netscape.cmsutil.util.Utils.getStringArrayFromVector(v); + } + + private SubjectDirAttributesExtension formExt(IRequest req) + throws IOException { + Vector attrs = new Vector(); + + // if we're called from init and one attribute is from request attribute + // the ext can't be formed yet. + if (req == null) { + for (int i = 0; i < mNumAttributes; i++) { + if (mAttributes[i].mWhereToGetValue == + AttributeConfig.USE_REQUEST_ATTR) + return null; + } + } + // either we're called from apply or all values are fixed. + for (int i = 0; i < mNumAttributes; i++) { + if (mAttributes[i].mAttribute != null) { + attrs.addElement(mAttributes[i].mAttribute); + } else { + // skip attribute if request attribute doesn't exist. + Attribute a = mAttributes[i].formAttr(req); + + if (a == null) + continue; + attrs.addElement(a); + } + } + if (attrs.size() == 0) + return null; + Attribute[] attrList = new Attribute[attrs.size()]; + + attrs.copyInto(attrList); + SubjectDirAttributesExtension ext = + new SubjectDirAttributesExtension(attrList); + + return ext; + } +} + + +class AttributeConfig { + + protected static final String PROP_ATTRIBUTE_NAME = "attributeName"; + protected static final String PROP_WTG_VALUE = "whereToGetValue"; + protected static final String PROP_VALUE = "value"; + + protected static final String USE_REQUEST_ATTR = "Request Attribute"; + protected static final String USE_FIXED = "Fixed Value"; + + protected String mAttributeName = null; + protected String mWhereToGetValue = null; + protected String mValue = null; + + protected String mPrefix = null; + protected String mReqAttr = null; + protected ObjectIdentifier mAttributeOID = null; + + protected String mName = null; + protected IConfigStore mConfig = null; + protected Attribute mAttribute = null; + + protected static final String ATTRIBUTE_NAME_INFO = "Attribute name."; + protected static final String WTG_VALUE_INFO = + PROP_WTG_VALUE + ";choice(" + USE_REQUEST_ATTR + "," + USE_FIXED + ");" + + "Get value from a request attribute or use a fixed value specified below."; + protected static final String VALUE_INFO = + PROP_VALUE + ";string;" + + "Request attribute name or a fixed value to put into the extension."; + + public AttributeConfig(String name, IConfigStore config, boolean enabled) + throws EBaseException { + X500NameAttrMap map = X500NameAttrMap.getDefault(); + + mName = name; + mConfig = config; + if (enabled) { + mAttributeName = mConfig.getString(PROP_ATTRIBUTE_NAME); + mWhereToGetValue = mConfig.getString(PROP_WTG_VALUE); + mValue = mConfig.getString(PROP_VALUE); + } else { + mAttributeName = mConfig.getString(PROP_ATTRIBUTE_NAME, ""); + mWhereToGetValue = mConfig.getString(PROP_WTG_VALUE, USE_REQUEST_ATTR); + mValue = mConfig.getString(PROP_VALUE, ""); + } + + if (mAttributeName.length() > 0) { + mAttributeOID = map.getOid(mAttributeName); + if (mAttributeOID == null) + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", mAttributeName)); + } + + if (mWhereToGetValue.equalsIgnoreCase(USE_REQUEST_ATTR)) { + mWhereToGetValue = USE_REQUEST_ATTR; + if (enabled && mValue.length() == 0) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_GET_PROPERTY_FAILED", PROP_VALUE)); + } + int dot = mValue.indexOf('.'); + + if (dot != -1) { + mPrefix = mValue.substring(0, dot); + mReqAttr = mValue.substring(dot + 1); + if (mPrefix == null || mPrefix.length() == 0 || + mReqAttr == null || mReqAttr.length() == 0) { + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", mValue)); + } + } else { + mPrefix = null; + mReqAttr = mValue; + } + } else if (mWhereToGetValue.equalsIgnoreCase(USE_FIXED)) { + mWhereToGetValue = USE_FIXED; + if (mAttributeOID != null) { + try { + checkValue(mAttributeOID, mValue); + mAttribute = new Attribute(mAttributeOID, mValue); + } catch (Exception e) { + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + mAttributeName, e.getMessage())); + } + } + } else if (enabled || mWhereToGetValue.length() > 0) { + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_VALUE_FOR_TYPE", PROP_WTG_VALUE, + "Must be either '" + USE_REQUEST_ATTR + "' or '" + USE_FIXED + "'.")); + } + } + + public static void getDefaultParams(String name, Vector v) { + String nameDot = name + "."; + + v.addElement(nameDot + PROP_ATTRIBUTE_NAME + "="); + v.addElement(nameDot + PROP_WTG_VALUE + "=" + USE_REQUEST_ATTR); + v.addElement(nameDot + PROP_VALUE + "="); + } + + public static void getExtendedPluginInfo(String name, Vector v) { + String nameDot = name + "."; + String attrChoices = getAllNames(); + + v.addElement(nameDot + PROP_ATTRIBUTE_NAME + ";choice(" + attrChoices + ");" + + ATTRIBUTE_NAME_INFO); + v.addElement(nameDot + WTG_VALUE_INFO); + v.addElement(nameDot + VALUE_INFO); + } + + public void getInstanceParams(Vector v) { + String nameDot = mName + "."; + + v.addElement(nameDot + PROP_ATTRIBUTE_NAME + "=" + mAttributeName); + v.addElement(nameDot + PROP_WTG_VALUE + "=" + mWhereToGetValue); + v.addElement(nameDot + PROP_VALUE + "=" + mValue); + } + + public Attribute formAttr(IRequest req) + throws IOException { + String val = req.getExtDataInString(mPrefix, mReqAttr); + + if (val == null || val.length() == 0) { + return null; + } + checkValue(mAttributeOID, val); + return new Attribute(mAttributeOID, val); + } + + static private String getAllNames() { + Enumeration n = X500NameAttrMap.getDefault().getAllNames(); + StringBuffer sb = new StringBuffer(); + sb.append((String) n.nextElement()); + + while (n.hasMoreElements()) { + sb.append(","); + sb.append((String) n.nextElement()); + } + return sb.toString(); + } + + private static void checkValue(ObjectIdentifier oid, String val) + throws IOException { + AVAValueConverter c = X500NameAttrMap.getDefault().getValueConverter(oid); + DerValue derval; + + derval = c.getValue(val); // errs encountered will get thrown. + return; + } + +} |