diff options
author | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-24 02:27:47 -0500 |
---|---|---|
committer | Endi Sukma Dewata <edewata@redhat.com> | 2012-03-26 11:43:54 -0500 |
commit | 621d9e5c413e561293d7484b93882d985b3fe15f (patch) | |
tree | 638f3d75761c121d9a8fb50b52a12a6686c5ac5c /base/common/src/com/netscape/cms/policy/constraints | |
parent | 40d3643b8d91886bf210aa27f711731c81a11e49 (diff) | |
download | pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.gz pki-621d9e5c413e561293d7484b93882d985b3fe15f.tar.xz pki-621d9e5c413e561293d7484b93882d985b3fe15f.zip |
Removed unnecessary pki folder.
Previously the source code was located inside a pki folder.
This folder was created during svn migration and is no longer
needed. This folder has now been removed and the contents have
been moved up one level.
Ticket #131
Diffstat (limited to 'base/common/src/com/netscape/cms/policy/constraints')
16 files changed, 3860 insertions, 0 deletions
diff --git a/base/common/src/com/netscape/cms/policy/constraints/AgentPolicy.java b/base/common/src/com/netscape/cms/policy/constraints/AgentPolicy.java new file mode 100644 index 000000000..b7a24bd65 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/AgentPolicy.java @@ -0,0 +1,161 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.util.Vector; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.AgentApprovals; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * AgentPolicy is an enrollment policy wraps another policy module. + * Requests are sent first to the contained module, but if the + * policy indicates that the request should be deferred, a check + * for agent approvals is done. If any are found, the request + * is approved. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class AgentPolicy extends APolicyRule + implements IEnrollmentPolicy { + public AgentPolicy() { + NAME = "AgentPolicy"; + DESC = "Agent Approval Policy"; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries may be of the form: + * + * ra.Policy.rule.<ruleName>.implName=AgentPolicy ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o == netscape.com ra.Policy.rule.<ruleName>.class=xxxx + * ra.Policy.rule.<ruleName>.params.* + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + + // Create subordinate object + String className = (String) config.get("class"); + + System.err.println("Creating agent policy with class " + className); + if (className != null) { + IConfigStore substore = config.getSubStore("params"); + + try { + @SuppressWarnings("unchecked") + Class<APolicyRule> c = (Class<APolicyRule>) Class.forName(className); + + Object o = c.newInstance(); + + if (!(o instanceof APolicyRule)) { + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CLASS", + getInstanceName(), className)); + } + + APolicyRule pr = (APolicyRule) o; + + pr.init(owner, substore); + mPolicy = pr; + } catch (EPolicyException e) { + System.err.println("Agent Policy Error: " + e); + throw e; + } catch (Exception e) { + System.err.println("Agent Policy Error: " + e); + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_LOADING_POLICY_ERROR", + getInstanceName(), className)); + } + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + + // The default is to require manual approval for everything + PolicyResult result = PolicyResult.DEFERRED; + + // Give the underlying object a chance + if (mPolicy != null) { + result = mPolicy.apply(req); + System.err.println("Subordinate policy returns " + result); + } + + if (result == PolicyResult.DEFERRED) { + System.err.println("Checking agent approvals"); + // Try to find an agent approval + AgentApprovals aa = AgentApprovals.fromStringVector( + req.getExtDataInStringVector(AgentApprovals.class.getName())); + + //Object o = req.get("agentApprovals"); + + // Any approvals causes success + if (aa != null && aa.elements().hasMoreElements()) //if (o != null) + { + System.err.println("Agent approval found"); + result = PolicyResult.ACCEPTED; + } + } + System.err.println("Agent policy returns " + result); + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + return null; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return null; + } + + APolicyRule mPolicy = null; +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/AttributePresentConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/AttributePresentConstraints.java new file mode 100644 index 000000000..93327445e --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/AttributePresentConstraints.java @@ -0,0 +1,406 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; + +import netscape.ldap.LDAPAttribute; +import netscape.ldap.LDAPConnection; +import netscape.ldap.LDAPEntry; +import netscape.ldap.LDAPException; +import netscape.ldap.LDAPSearchResults; +import netscape.ldap.LDAPv2; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ldap.ILdapConnFactory; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.certsrv.request.RequestId; +import com.netscape.cms.policy.APolicyRule; + +/** + * This checks if attribute present. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class AttributePresentConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + protected static final String PROP_ENABLED = "enabled"; + protected static final String PROP_LDAP = "ldap"; + + protected String mName = null; + protected String mImplName = null; + + private boolean mEnabled = false; + private ILogger mLogger = CMS.getLogger(); + + private ICertAuthority mSub = null; + private IConfigStore mConfig = null; + private IConfigStore mLdapConfig = null; + private RequestId mReqId = null; + private ILdapConnFactory mConnFactory = null; + private LDAPConnection mCheckAttrLdapConnection = null; + + public AttributePresentConstraints() { + DESC = "Rejects request if ldap attribute is not present in the " + + "directory."; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String params[] = { + PROP_ATTR + ";string,required;Ldap attribute to check presence of (default " + + DEF_ATTR + ")", + PROP_VALUE + ";string;if this parameter is non-empty, the attribute must " + + "match this value for the request to proceed ", + PROP_LDAP_BASE + ";string,required;Base DN to start searching " + + "under. If your user's DN is 'uid=jsmith, o=company', you " + + "might want to use 'o=company' here", + PROP_LDAP_HOST + ";string,required;" + + "LDAP host to connect to", + PROP_LDAP_PORT + ";number,required;" + + "LDAP port number (use 389, or 636 if SSL)", + PROP_LDAP_SSL + ";boolean;" + + "Use SSL to connect to directory?", + PROP_LDAP_VER + ";choice(3,2),required;" + + "LDAP protocol version", + PROP_LDAP_BIND + ";string;DN to bind as for attribute checking. " + + "For example 'CN=Pincheck User'", + PROP_LDAP_PW + ";password;Enter password used to bind as " + + "the above user", + PROP_LDAP_AUTH + ";choice(BasicAuth,SslClientAuth),required;" + + "How to bind to the directory", + PROP_LDAP_CERT + ";string;If you want to use " + + "SSL client auth to the directory, set the client " + + "cert nickname here", + PROP_LDAP_BASE + ";string,required;Base DN to start searching " + + "under. If your user's DN is 'uid=jsmith, o=company', you " + + "might want to use 'o=company' here", + PROP_LDAP_MINC + ";number;number of connections " + + "to keep open to directory server. Default " + DEF_LDAP_MINC, + PROP_LDAP_MAXC + ";number;when needed, connection " + + "pool can grow to this many (multiplexed) connections. Default " + DEF_LDAP_MAXC, + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-pinpresent", + IExtendedPluginInfo.HELP_TEXT + + ";" + DESC + " This plugin can be used to " + + "check the presence (and, optionally, the value) of any LDAP " + + "attribute for the user. " + }; + + return params; + } + + public String getName() { + return mName; + } + + public String getImplName() { + return mImplName; + } + + public IConfigStore getConfigStore() { + return mConfig; + } + + public void shutdown() { + } + + // Parameters + + protected static final String PROP_LDAP_HOST = "ldap.ldapconn.host"; + protected static final String DEF_LDAP_HOST = "localhost"; + + protected static final String PROP_LDAP_PORT = "ldap.ldapconn.port"; + protected static final Integer DEF_LDAP_PORT = Integer.valueOf(389); + + protected static final String PROP_LDAP_SSL = "ldap.ldapconn.secureConn"; + protected static final Boolean DEF_LDAP_SSL = Boolean.FALSE; + + protected static final String PROP_LDAP_VER = "ldap.ldapconn.version"; + protected static final Integer DEF_LDAP_VER = Integer.valueOf(3); + + protected static final String PROP_LDAP_BIND = "ldap.ldapauth.bindDN"; + protected static final String DEF_LDAP_BIND = "CN=Directory Manager"; + + protected static final String PROP_LDAP_PW = "ldap.ldapauth.bindPWPrompt"; + protected static final String DEF_LDAP_PW = ""; + + protected static final String PROP_LDAP_CERT = "ldap.ldapauth.clientCertNickname"; + protected static final String DEF_LDAP_CERT = ""; + + protected static final String PROP_LDAP_AUTH = "ldap.ldapauth.authtype"; + protected static final String DEF_LDAP_AUTH = "BasicAuth"; + + protected static final String PROP_LDAP_BASE = "ldap.ldapconn.basedn"; + protected static final String DEF_LDAP_BASE = ""; + + protected static final String PROP_LDAP_MINC = "ldap.ldapconn.minConns"; + protected static final Integer DEF_LDAP_MINC = Integer.valueOf(1); + + protected static final String PROP_LDAP_MAXC = "ldap.ldapconn.maxConns"; + protected static final Integer DEF_LDAP_MAXC = Integer.valueOf(5); + + protected static final String PROP_ATTR = "attribute"; + protected static final String DEF_ATTR = "pin"; + + protected static final String PROP_VALUE = "value"; + protected static final String DEF_VALUE = ""; + + protected static Vector<String> mParamNames; + protected static Hashtable<String, Object> mParamDefault; + protected Hashtable<String, Object> mParamValue = null; + + static { + mParamNames = new Vector<String>(); + mParamDefault = new Hashtable<String, Object>(); + addParam(PROP_LDAP_HOST, DEF_LDAP_HOST); + addParam(PROP_LDAP_PORT, DEF_LDAP_PORT); + addParam(PROP_LDAP_SSL, DEF_LDAP_SSL); + addParam(PROP_LDAP_VER, DEF_LDAP_VER); + addParam(PROP_LDAP_BIND, DEF_LDAP_BIND); + addParam(PROP_LDAP_PW, DEF_LDAP_PW); + addParam(PROP_LDAP_CERT, DEF_LDAP_CERT); + addParam(PROP_LDAP_AUTH, DEF_LDAP_AUTH); + addParam(PROP_LDAP_BASE, DEF_LDAP_BASE); + addParam(PROP_LDAP_MINC, DEF_LDAP_MINC); + addParam(PROP_LDAP_MAXC, DEF_LDAP_MAXC); + addParam(PROP_ATTR, DEF_ATTR); + addParam(PROP_VALUE, DEF_VALUE); + }; + + protected static void addParam(String name, Object value) { + mParamNames.addElement(name); + mParamDefault.put(name, value); + } + + protected void getStringConfigParam(IConfigStore config, String paramName) { + try { + mParamValue.put( + paramName, config.getString(paramName, (String) mParamDefault.get(paramName)) + ); + } catch (Exception e) { + } + } + + protected void getIntConfigParam(IConfigStore config, String paramName) { + try { + mParamValue.put( + paramName, Integer.valueOf( + config.getInteger(paramName, + ((Integer) mParamDefault.get(paramName)).intValue() + ) + ) + ); + } catch (Exception e) { + } + } + + protected void getBooleanConfigParam(IConfigStore config, String paramName) { + try { + mParamValue.put( + paramName, Boolean.valueOf( + config.getBoolean(paramName, + ((Boolean) mParamDefault.get(paramName)).booleanValue() + ) + ) + ); + } catch (Exception e) { + } + } + + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + mConfig = config; + + mParamValue = new Hashtable<String, Object>(); + + getStringConfigParam(mConfig, PROP_LDAP_HOST); + getIntConfigParam(mConfig, PROP_LDAP_PORT); + getBooleanConfigParam(mConfig, PROP_LDAP_SSL); + getIntConfigParam(mConfig, PROP_LDAP_VER); + getStringConfigParam(mConfig, PROP_LDAP_BIND); + getStringConfigParam(mConfig, PROP_LDAP_PW); + getStringConfigParam(mConfig, PROP_LDAP_CERT); + getStringConfigParam(mConfig, PROP_LDAP_AUTH); + getStringConfigParam(mConfig, PROP_LDAP_BASE); + getIntConfigParam(mConfig, PROP_LDAP_MINC); + getIntConfigParam(mConfig, PROP_LDAP_MAXC); + getStringConfigParam(mConfig, PROP_ATTR); + getStringConfigParam(mConfig, PROP_VALUE); + + mLdapConfig = mConfig.getSubStore(PROP_LDAP); + + mConnFactory = CMS.getLdapBoundConnFactory(); + mConnFactory.init(mLdapConfig); + mCheckAttrLdapConnection = mConnFactory.getConn(); + + } + + public PolicyResult apply(IRequest r) { + PolicyResult res = PolicyResult.ACCEPTED; + + mReqId = r.getRequestId(); + + String requestType = r.getRequestType(); + + if (requestType.equals(IRequest.ENROLLMENT_REQUEST) || + requestType.equals(IRequest.RENEWAL_REQUEST)) { + + String uid = r.getExtDataInString(IRequest.HTTP_PARAMS, "uid"); + + if (uid == null) { + log(ILogger.LL_INFO, "did not find UID parameter in request " + r.getRequestId()); + setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), ""); + return PolicyResult.REJECTED; + } + + String userdn = null; + + try { + String[] attrs = { (String) mParamValue.get(PROP_ATTR) }; + LDAPSearchResults searchResult = + mCheckAttrLdapConnection.search((String) mParamValue.get(PROP_LDAP_BASE), + LDAPv2.SCOPE_SUB, "(uid=" + uid + ")", attrs, false); + + if (!searchResult.hasMoreElements()) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", uid)); + setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), ""); + return PolicyResult.REJECTED; + } + + LDAPEntry entry = (LDAPEntry) searchResult.nextElement(); + + userdn = entry.getDN(); + + LDAPAttribute attr = entry.getAttribute((String) mParamValue.get(PROP_ATTR)); + + /* if attribute not present, reject the request */ + if (attr == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", userdn)); + setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), ""); + return PolicyResult.REJECTED; + } + String acceptedValue = ((String) mParamValue.get(PROP_VALUE)); + + if (!acceptedValue.equals("")) { + int matches = 0; + + String[] values = attr.getStringValueArray(); + + for (int i = 0; i < values.length; i++) { + if (values[i].equals(acceptedValue)) { + matches++; + } + } + if (matches == 0) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMS_AUTH_NO_PIN_FOUND", userdn)); + setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), ""); + return PolicyResult.REJECTED; + } + } + + CMS.debug("AttributePresentConstraints: Attribute is present for user: \"" + userdn + "\""); + + } catch (LDAPException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_PIN_UNAUTHORIZED")); + setError(r, CMS.getUserMessage("CMS_POLICY_PIN_UNAUTHORIZED"), ""); + return PolicyResult.REJECTED; + } + + } + return res; + } + + public Vector<String> getInstanceParams() { + Vector<String> params = new Vector<String>(); + + Enumeration<String> e = mParamNames.elements(); + + while (e.hasMoreElements()) { + try { + String paramName = (String) e.nextElement(); + String paramValue = mParamValue.get(paramName).toString(); + String temp = paramName + "=" + paramValue; + + params.addElement(temp); + } catch (Exception ex) { + } + } + + return params; + } + + public Vector<String> getDefaultParams() { + Vector<String> params = new Vector<String>(); + + Enumeration<String> e = mParamNames.elements(); + + while (e.hasMoreElements()) { + try { + String paramName = (String) e.nextElement(); + String paramValue = mParamDefault.get(paramName).toString(); + String temp = paramName + "=" + paramValue; + + params.addElement(temp); + } catch (Exception ex) { + } + } + + return params; + + /* + params.addElement("ldap.ldapconn.host=localhost"); + params.addElement("ldap.ldapconn.port=389"); + params.addElement("ldap.ldapconn.secureConn=false"); + params.addElement("ldap.ldapconn.version=3"); + params.addElement("ldap.ldapauth.bindDN=CN=Directory Manager"); + params.addElement("ldap.ldapauth.bindPWPrompt="); + params.addElement("ldap.ldapauth.clientCertNickname="); + params.addElement("ldap.ldapauth.authtype=BasicAuth"); + params.addElement("ldap.basedn="); + params.addElement("ldap.minConns=1"); + params.addElement("ldap.maxConns=5"); + */ + } + + protected void log(int level, String msg) { + if (mLogger == null) + return; + + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_OTHER, + level, "AttributePresentConstraints: " + msg); + } + +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/DSAKeyConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/DSAKeyConstraints.java new file mode 100644 index 000000000..387b702bf --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/DSAKeyConstraints.java @@ -0,0 +1,252 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.math.BigInteger; +import java.security.interfaces.DSAParams; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.provider.DSAPublicKey; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * DSAKeyConstraints policy enforces min and max size of the key. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class DSAKeyConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + private int mMinSize; + private int mMaxSize; + + private final static int INCREMENT = 64; + private final static int DEF_MIN_SIZE = 512; + private final static int DEF_MAX_SIZE = 1024; + + private final static String DSA = "DSA"; + private final static String PROP_MIN_SIZE = "minSize"; + private final static String PROP_MAX_SIZE = "maxSize"; + + private final static Vector<String> defConfParams = new Vector<String>(); + + private IConfigStore mConfig = null; + + static { + defConfParams.addElement(PROP_MIN_SIZE + "=" + DEF_MIN_SIZE); + defConfParams.addElement(PROP_MAX_SIZE + "=" + DEF_MAX_SIZE); + } + + public DSAKeyConstraints() { + NAME = "DSAKeyConstraints"; + DESC = "Enforces DSA Key Constraints."; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_MIN_SIZE + ";number;Minimum key size", + PROP_MAX_SIZE + ";number;Maximum key size", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-dsakeyconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Rejects request if DSA key size is out of range" + }; + + return params; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=DSAKeyConstraints + * ra.Policy.rule.<ruleName>.enable=true ra.Policy.rule.<ruleName>.minSize=512 + * ra.Policy.rule.<ruleName>.maxSize=1024 ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o == + * netscape.com + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + + // Get Min and Max sizes + mConfig = config; + + try { + mMinSize = config.getInteger(PROP_MIN_SIZE, DEF_MIN_SIZE); + mMaxSize = config.getInteger(PROP_MAX_SIZE, DEF_MAX_SIZE); + + if (mMaxSize > DEF_MAX_SIZE) { + String msg = "cannot be more than " + DEF_MAX_SIZE; + + log(ILogger.LL_FAILURE, PROP_MAX_SIZE + " " + msg); + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + PROP_MAX_SIZE, msg)); + } + if (mMinSize < DEF_MIN_SIZE) { + String msg = "cannot be less than " + DEF_MIN_SIZE; + + log(ILogger.LL_FAILURE, PROP_MIN_SIZE + " " + msg); + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + PROP_MIN_SIZE, msg)); + } + if (mMaxSize % INCREMENT != 0) { + String msg = "must be in increments of " + INCREMENT; + + log(ILogger.LL_FAILURE, PROP_MAX_SIZE + " " + msg); + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + PROP_MIN_SIZE, msg)); + } + if (mMaxSize % INCREMENT != 0) { + String msg = "must be in increments of " + INCREMENT; + + log(ILogger.LL_FAILURE, PROP_MIN_SIZE + " " + msg); + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_INVALID_ATTR_VALUE", + PROP_MIN_SIZE, msg)); + } + + config.putInteger(PROP_MIN_SIZE, mMinSize); + config.putInteger(PROP_MAX_SIZE, mMaxSize); + + } catch (Exception e) { + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", getInstanceName(), e.toString())); + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + + PolicyResult result = PolicyResult.ACCEPTED; + + try { + // Get the certificate info from the request + X509CertInfo ci[] = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + // There should be a certificate info set. + if (ci == null || ci[0] == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", NAME), ""); + return PolicyResult.REJECTED; + } + + // Else check if the key size(s) are within the limit. + for (int i = 0; i < ci.length; i++) { + CertificateX509Key certKey = (CertificateX509Key) + ci[i].get(X509CertInfo.KEY); + X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY); + String alg = key.getAlgorithmId().toString(); + + if (!alg.equalsIgnoreCase(DSA)) + continue; + + // Check DSAKey parameters. + // size refers to the p parameter. + DSAPublicKey dsaKey = new DSAPublicKey(key.getEncoded()); + DSAParams keyParams = dsaKey.getParams(); + + if (keyParams == null) { + // key parameters could not be parsed. + setError(req, + CMS.getUserMessage("CMS_POLICY_NO_KEY_PARAMS", getInstanceName(), String.valueOf(i + 1)), + ""); + return PolicyResult.REJECTED; + } + BigInteger p = keyParams.getP(); + int len = p.bitLength(); + + if (len < mMinSize || len > mMaxSize || + (len % INCREMENT) != 0) { + String[] parms = new String[] { + getInstanceName(), + String.valueOf(len), + String.valueOf(mMinSize), + String.valueOf(mMaxSize), + String.valueOf(INCREMENT) }; + + setError(req, CMS.getUserMessage("CMS_POLICY_KEY_SIZE_VIOLATION_1", parms), ""); + return PolicyResult.REJECTED; + } + } + } catch (Exception e) { + // e.printStackTrace(); + String[] params = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + try { + confParams.addElement(PROP_MIN_SIZE + "=" + mConfig.getInteger(PROP_MIN_SIZE, DEF_MIN_SIZE)); + confParams.addElement(PROP_MAX_SIZE + "=" + mConfig.getInteger(PROP_MAX_SIZE, DEF_MAX_SIZE)); + } catch (EBaseException e) { + ; + } + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return defConfParams; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/DefaultRevocation.java b/base/common/src/com/netscape/cms/policy/constraints/DefaultRevocation.java new file mode 100644 index 000000000..2af145475 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/DefaultRevocation.java @@ -0,0 +1,104 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +import java.util.Locale; +import java.util.Vector; + +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IRevocationPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * This is the default revocation policy. Currently this does + * nothing. We can later add checks like whether or not to + * revoke expired certs ..etc here. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class DefaultRevocation extends APolicyRule + implements IRevocationPolicy, IExtendedPluginInfo { + public DefaultRevocation() { + NAME = "DefaultRevocation"; + DESC = "Default Revocation Policy"; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries may be of the form: + * + * ra.Policy.rule.<ruleName>.implName=DefaultRevocation ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o == netscape.com + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + return PolicyResult.ACCEPTED; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + return null; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return null; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-defaultrevocation" + }; + + return params; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/IssuerConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/IssuerConstraints.java new file mode 100644 index 000000000..a08bde78c --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/IssuerConstraints.java @@ -0,0 +1,216 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +import java.util.Locale; +import java.util.Vector; + +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * IssuerConstraints is a rule for restricting the issuers of the + * certificates used for certificate-based enrollments. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$ $Date$ + */ +public class IssuerConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + private final static String PROP_ISSUER_DN = "issuerDN"; + private static final String CLIENT_ISSUER = "clientIssuer"; + private X500Name mIssuerDN = null; + private String mIssuerDNString; + + /** + * checks the issuer of the ssl client-auth cert. Only one issuer + * is allowed for now + */ + public IssuerConstraints() { + NAME = "IssuerConstraints"; + DESC = "Checks to see if the Issuer is one allowed"; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_ISSUER_DN + + ";string;Subject DN of the Issuer. The IssuerDN of the authenticating cert must match what's specified here", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-issuerconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Rejects the request if the issuer in the certificate is" + + "not of the one specified" + }; + + return params; + + } + + /** + * Initializes this policy rule. + * <P> + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + try { + mIssuerDNString = config.getString(PROP_ISSUER_DN, null); + if ((mIssuerDNString != null) && + !mIssuerDNString.equals("")) { + mIssuerDN = new X500Name(mIssuerDNString); + } + } catch (Exception e) { + log(ILogger.LL_FAILURE, + NAME + CMS.getLogMessage("CA_GET_ISSUER_NAME_FAILED")); + + String[] params = { getInstanceName(), e.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params)); + } + CMS.debug( + NAME + ": init() done"); + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + PolicyResult result = PolicyResult.ACCEPTED; + + if (mIssuerDN == null) + return result; + + try { + String clientIssuerDN = req.getExtDataInString(CLIENT_ISSUER); + + if (clientIssuerDN != null) { + X500Name ci_name = new X500Name(clientIssuerDN); + + if (!ci_name.equals(mIssuerDN)) { + setError(req, + CMS.getUserMessage("CMS_POLICY_INVALID_ISSUER", + getInstanceName()), ""); + result = PolicyResult.REJECTED; + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CA_GET_ISSUER_NAME_FAILED")); + CMS.debug( + NAME + ": apply() - issuerDN mismatch: client issuerDN = " + clientIssuerDN + + "; expected issuerDN = " + mIssuerDNString); + } + } else { + + // Get the certificate info from the request + X509CertInfo certInfo[] = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + if (certInfo == null) { + log(ILogger.LL_FAILURE, + NAME + ": apply() - missing certInfo"); + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + for (int i = 0; i < certInfo.length; i++) { + String oldIssuer = (String) + certInfo[i].get(X509CertInfo.ISSUER).toString(); + + if (oldIssuer == null) { + setError(req, + CMS.getUserMessage("CMS_POLICY_CLIENT_ISSUER_NOT_FOUND", + getInstanceName()), ""); + result = PolicyResult.REJECTED; + log(ILogger.LL_FAILURE, + NAME + ": apply() - client issuerDN not found"); + } + X500Name oi_name = new X500Name(oldIssuer); + + if (!oi_name.equals(mIssuerDN)) { + setError(req, + CMS.getUserMessage("CMS_POLICY_INVALID_ISSUER", + getInstanceName()), ""); + result = PolicyResult.REJECTED; + log(ILogger.LL_FAILURE, + NAME + ": apply() - cert issuerDN mismatch: client issuerDN = " + oldIssuer + + "; expected issuerDN = " + mIssuerDNString); + } + } + } + } catch (Exception e) { + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), ""); + result = PolicyResult.REJECTED; + } + + if (result.equals(PolicyResult.ACCEPTED)) { + log(ILogger.LL_INFO, + NAME + ": apply() - accepted"); + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + confParams.addElement(PROP_ISSUER_DN + "=" + + mIssuerDNString); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + Vector<String> defParams = new Vector<String>(); + + defParams.addElement(PROP_ISSUER_DN + "="); + return defParams; + } + +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/KeyAlgorithmConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/KeyAlgorithmConstraints.java new file mode 100644 index 000000000..3779b16e3 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/KeyAlgorithmConstraints.java @@ -0,0 +1,225 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * KeyAlgorithmConstraints enforces a constraint that the RA or a CA + * honor only the keys generated using one of the permitted algorithms + * such as RSA, DSA or DH. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class KeyAlgorithmConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + private Vector<String> mAlgorithms; + private final static String DEF_KEY_ALGORITHM = "RSA,DSA"; + private final static String PROP_ALGORITHMS = "algorithms"; + private final static String[] supportedAlgorithms = + { "RSA", "DSA", "DH" }; + + private final static Vector<String> defConfParams = new Vector<String>(); + + static { + defConfParams.addElement(PROP_ALGORITHMS + "=" + + DEF_KEY_ALGORITHM); + } + + public String[] getExtendedPluginInfo(Locale locale) { + String params[] = { + "algorithms;choice(RSA\\,DSA,RSA,DSA);Certificate's key can be one of these algorithms", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-keyalgorithmconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Rejects the request if the key in the certificate is " + + "not of the type specified" + }; + + return params; + } + + public KeyAlgorithmConstraints() { + NAME = "KeyAlgorithmConstraints"; + DESC = "Enforces Key Algorithm Constraints."; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=KeyAlgorithmConstraints + * ra.Policy.rule.<ruleName>.algorithms=RSA,DSA ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.predicate=ou==Sales + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + + mAlgorithms = new Vector<String>(); + + if (config == null || config.size() == 0) { + mAlgorithms.addElement(DEF_KEY_ALGORITHM); + return; + } + + // Get Algorithm names + String algNames = null; + + try { + algNames = config.getString(PROP_ALGORITHMS, null); + } catch (Exception e) { + String[] params = { getInstanceName(), e.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params)); + } + + if (algNames == null) { + mAlgorithms.addElement(DEF_KEY_ALGORITHM); + return; + } + StringTokenizer tok = new StringTokenizer(algNames, ","); + + while (tok.hasMoreTokens()) { + String alg = tok.nextToken().trim().toUpperCase(); + + if (alg.length() == 0) + continue; + mAlgorithms.addElement(alg); + } + + // Check if configured algorithms are supported. + for (Enumeration<String> e = mAlgorithms.elements(); e.hasMoreElements();) { + int i; + String configuredAlg = e.nextElement(); + + // See if it is a supported algorithm. + for (i = 0; i < supportedAlgorithms.length; i++) { + if (configuredAlg.equals(supportedAlgorithms[i])) + break; + } + + // Did we not find it? + if (i == supportedAlgorithms.length) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_UNSUPPORTED_KEY_ALG", + getInstanceName(), configuredAlg)); + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + + PolicyResult result = PolicyResult.ACCEPTED; + + try { + // Get the certificate info from the request + // X509CertInfo certInfo[] = (X509CertInfo[]) + // req.get(IRequest.CERT_INFO); + X509CertInfo certInfo[] = req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + // We need to have a certificate info set + if (certInfo == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + // Else check if the key algorithm is supported. + for (int i = 0; i < certInfo.length; i++) { + CertificateX509Key certKey = (CertificateX509Key) + certInfo[i].get(X509CertInfo.KEY); + X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY); + String alg = key.getAlgorithmId().getName().toUpperCase(); + + if (!mAlgorithms.contains(alg)) { + setError(req, CMS.getUserMessage("CMS_POLICY_KEY_ALG_VIOLATION", + getInstanceName(), alg), ""); + result = PolicyResult.REJECTED; + } + } + } catch (Exception e) { + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", + params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> v = new Vector<String>(); + StringBuffer sb = new StringBuffer(); + + for (Enumeration<String> e = mAlgorithms.elements(); e.hasMoreElements();) { + sb.append(e.nextElement()); + sb.append(","); + } + if (sb.length() > 0) + sb.setLength(sb.length() - 1); + v.addElement(PROP_ALGORITHMS + "=" + sb.toString()); + return v; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return defConfParams; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/ManualAuthentication.java b/base/common/src/com/netscape/cms/policy/constraints/ManualAuthentication.java new file mode 100644 index 000000000..3af9e636f --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/ManualAuthentication.java @@ -0,0 +1,101 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +import java.util.Vector; + +import com.netscape.certsrv.authentication.IAuthToken; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * ManualAuthentication is an enrollment policy that queues + * all requests for issuing agent's approval if no authentication + * is present. The policy rejects a request if any of the auth tokens + * indicates authentication failure. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class ManualAuthentication extends APolicyRule + implements IEnrollmentPolicy { + public ManualAuthentication() { + NAME = "ManualAuthentication"; + DESC = "Manual Authentication Policy"; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries may be of the form: + * + * ra.Policy.rule.<ruleName>.implName=ManualAuthentication ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.predicate= ou == engineering AND o == netscape.com + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + IAuthToken authToken = req.getExtDataInAuthToken(IRequest.AUTH_TOKEN); + + if (authToken == null) + return deferred(req); + + return PolicyResult.ACCEPTED; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + return null; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return null; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/RSAKeyConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/RSAKeyConstraints.java new file mode 100644 index 000000000..7c53808c5 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/RSAKeyConstraints.java @@ -0,0 +1,280 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +import java.util.Enumeration; +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import netscape.security.provider.RSAPublicKey; +import netscape.security.util.BigInt; +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateX509Key; +import netscape.security.x509.X509CertInfo; +import netscape.security.x509.X509Key; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * RSAKeyConstraints policy enforces min and max size of the key. + * Optionally checks the exponents. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class RSAKeyConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + private Vector<BigInt> mExponents; + private int mMinSize; + private int mMaxSize; + + private final static int DEF_MIN_SIZE = 512; + private final static int DEF_MAX_SIZE = 2048; + private final static String PROP_MIN_SIZE = "minSize"; + private final static String PROP_MAX_SIZE = "maxSize"; + private final static String PROP_EXPONENTS = "exponents"; + private final static String RSA = "RSA"; + + private final static Vector<String> defConfParams = new Vector<String>(); + + static { + defConfParams.addElement(PROP_MIN_SIZE + "=" + DEF_MIN_SIZE); + defConfParams.addElement(PROP_MAX_SIZE + "=" + DEF_MAX_SIZE); + defConfParams.addElement(PROP_EXPONENTS + "=" + " "); + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_MIN_SIZE + ";number;Minimum size of user's RSA key (bits)", + PROP_MAX_SIZE + ";number;Maximum size of user's RSA key (bits)", + PROP_EXPONENTS + ";string;Comma-separated list of permissible exponents", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-rsakeyconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Reject request if RSA key length is not within the " + + "specified constraints" + }; + + return params; + } + + public RSAKeyConstraints() { + NAME = "RSAKeyConstraints"; + DESC = "Enforces RSA Key Constraints."; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form: + * + * ra.Policy.rule.<ruleName>.implName=RSAKeyConstraints ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.minSize=512 ra.Policy.rule.<ruleName>.maxSize=2048 + * ra.Policy.rule.<ruleName>.predicate=ou==Marketing + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + + if (config == null || config.size() == 0) + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_MISSING_POLICY_CONFIG", + getInstanceName())); + String exponents = null; + + // Get Min and Max sizes + mMinSize = config.getInteger(PROP_MIN_SIZE, DEF_MIN_SIZE); + mMaxSize = config.getInteger(PROP_MAX_SIZE, DEF_MAX_SIZE); + + if (mMinSize <= 0) + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_MUST_BE_POSITIVE_NUMBER", PROP_MIN_SIZE)); + if (mMaxSize <= 0) + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_MUST_BE_POSITIVE_NUMBER", PROP_MAX_SIZE)); + + if (mMinSize > mMaxSize) + throw new EBaseException( + CMS.getUserMessage("CMS_BASE_A_GREATER_THAN_EQUAL_B", PROP_MIN_SIZE, PROP_MAX_SIZE)); + + mExponents = new Vector<BigInt>(); + + // Get exponents + exponents = config.getString(PROP_EXPONENTS, null); + + if (exponents != null) { + StringTokenizer tok = new StringTokenizer(exponents, ","); + + try { + while (tok.hasMoreTokens()) { + String exp = tok.nextToken().trim(); + + mExponents.addElement(new BigInt(Integer.parseInt(exp))); + } + } catch (Exception e) { + // e.printStackTrace(); + String[] params = { getInstanceName(), exponents, + PROP_EXPONENTS }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_CONFIG_PARAM", params)); + } + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + + PolicyResult result = PolicyResult.ACCEPTED; + + try { + // Get the certificate info from the request + X509CertInfo certInfo[] = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + // There should be a certificate info set. + if (certInfo == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + // Else check if the key size(s) are within the limit. + for (int i = 0; i < certInfo.length; i++) { + CertificateX509Key certKey = (CertificateX509Key) + certInfo[i].get(X509CertInfo.KEY); + X509Key key = (X509Key) certKey.get(CertificateX509Key.KEY); + String alg = key.getAlgorithmId().toString(); + + if (!alg.equalsIgnoreCase(RSA)) + continue; + X509Key newkey = null; + + try { + newkey = new X509Key(AlgorithmId.get("RSA"), + key.getKey()); + } catch (Exception e) { + CMS.debug("RSAKeyConstraints::apply() - " + + "Exception=" + e.toString()); + setError(req, + CMS.getUserMessage("CMS_POLICY_KEY_SIZE_VIOLATION", + getInstanceName()), + ""); + return PolicyResult.REJECTED; + } + RSAPublicKey rsaKey = new RSAPublicKey(newkey.getEncoded()); + int keySize = rsaKey.getKeySize(); + + if (keySize < mMinSize || keySize > mMaxSize) { + String[] params = { getInstanceName(), + String.valueOf(keySize), + String.valueOf(mMinSize), + String.valueOf(mMaxSize) }; + + setError(req, CMS.getUserMessage("CMS_POLICY_KEY_SIZE_VIOLATION", + params), ""); + result = PolicyResult.REJECTED; + } + + // If the exponents are configured, see if the key's + // exponent is a configured one. + if (mExponents.size() > 0) { + BigInt exp = rsaKey.getPublicExponent(); + + if (!mExponents.contains(exp)) { + StringBuffer sb = new StringBuffer(); + + for (Enumeration<BigInt> e = mExponents.elements(); e.hasMoreElements();) { + BigInt bi = (BigInt) e.nextElement(); + + sb.append(bi.toBigInteger().toString()); + sb.append(" "); + } + String[] params = { getInstanceName(), + exp.toBigInteger().toString(), new String(sb) }; + + setError(req, CMS.getUserMessage("CMS_POLICY_EXPONENT_VIOLATION", params), ""); + result = PolicyResult.REJECTED; + } + } + } + } catch (Exception e) { + // e.printStackTrace(); + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + confParams.addElement(PROP_MIN_SIZE + "=" + mMinSize); + confParams.addElement(PROP_MAX_SIZE + "=" + mMaxSize); + StringBuffer sb = new StringBuffer(); + + for (Enumeration<BigInt> e = mExponents.elements(); e.hasMoreElements();) { + sb.append(e.nextElement().toInt()); + sb.append(","); + } + if (sb.length() > 0) + sb.setLength(sb.length() - 1); + confParams.addElement(PROP_EXPONENTS + "=" + sb.toString()); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return defConfParams; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/RenewalConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/RenewalConstraints.java new file mode 100644 index 000000000..f3e5efc9b --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/RenewalConstraints.java @@ -0,0 +1,242 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +import java.util.Date; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IRenewalPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * Whether to allow renewal of an expired cert. + * + * @version $Revision$, $Date$ + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class RenewalConstraints extends APolicyRule + implements IRenewalPolicy, IExtendedPluginInfo { + + private static final String PROP_ALLOW_EXPIRED_CERTS = "allowExpiredCerts"; + private static final String PROP_RENEWAL_NOT_AFTER = "renewalNotAfter"; + + private boolean mAllowExpiredCerts = true; + private long mRenewalNotAfter = 0; + + public final static int DEF_RENEWAL_NOT_AFTER = 30; + public final static long DAYS_TO_MS_FACTOR = 24L * 3600 * 1000; + + private final static Vector<String> defConfParams = new Vector<String>(); + static { + defConfParams.addElement(PROP_ALLOW_EXPIRED_CERTS + "=" + true); + defConfParams.addElement(PROP_RENEWAL_NOT_AFTER + "=" + + DEF_RENEWAL_NOT_AFTER); + } + + public RenewalConstraints() { + NAME = "RenewalConstraints"; + DESC = "Whether to allow renewal of expired certs."; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_ALLOW_EXPIRED_CERTS + ";boolean;Allow a user to renew an already-expired certificate", + PROP_RENEWAL_NOT_AFTER + + ";number;Number of days since certificate expiry after which renewal request would be rejected", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-renewalconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Permit administrator to decide policy on whether to " + + "permit renewals for already-expired certificates" + }; + + return params; + + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form: + * + * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.allowExpiredCerts=true + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + // Get min and max validity in days and configure them. + try { + mAllowExpiredCerts = + config.getBoolean(PROP_ALLOW_EXPIRED_CERTS, true); + String val = config.getString(PROP_RENEWAL_NOT_AFTER, null); + + if (val == null) + mRenewalNotAfter = DEF_RENEWAL_NOT_AFTER * DAYS_TO_MS_FACTOR; + else { + mRenewalNotAfter = Long.parseLong(val) * DAYS_TO_MS_FACTOR; + } + + } catch (EBaseException e) { + // never happen. + } + + CMS.debug("RenewalConstraints: allow expired certs " + mAllowExpiredCerts); + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + PolicyResult result = PolicyResult.ACCEPTED; + + try { + // Get the certificates being renwed. + X509CertImpl[] oldCerts = + req.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (oldCerts == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_OLD_CERT", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + if (mAllowExpiredCerts) { + CMS.debug("checking validity of each cert"); + // check if each cert to be renewed is expired for more than // allowed days. + for (int i = 0; i < oldCerts.length; i++) { + X509CertInfo oldCertInfo = (X509CertInfo) + oldCerts[i].get(X509CertImpl.NAME + "." + + X509CertImpl.INFO); + CertificateValidity oldValidity = (CertificateValidity) + oldCertInfo.get(X509CertInfo.VALIDITY); + Date notAfter = (Date) + oldValidity.get(CertificateValidity.NOT_AFTER); + + // Is the Certificate eligible for renewal ? + + Date now = CMS.getCurrentDate(); + + Date renewedNotAfter = new Date(notAfter.getTime() + + mRenewalNotAfter); + + CMS.debug("RenewalConstraints: cert " + i + " renewedNotAfter " + renewedNotAfter + " now=" + now); + + if (renewedNotAfter.before(now)) { + CMS.debug( + "One or more certificates is expired for more than " + + (mRenewalNotAfter / DAYS_TO_MS_FACTOR) + " days"); + String params[] = { getInstanceName(), Long.toString(mRenewalNotAfter / DAYS_TO_MS_FACTOR) }; + + setError(req, + CMS.getUserMessage("CMS_POLICY_CANNOT_RENEW_EXPIRED_CERTS_AFTER_ALLOWED_PERIOD", + params), ""); + return PolicyResult.REJECTED; + } + } + return PolicyResult.ACCEPTED; + } + + CMS.debug("RenewalConstraints: checking validity of each cert"); + // check if each cert to be renewed is expired. + for (int i = 0; i < oldCerts.length; i++) { + X509CertInfo oldCertInfo = (X509CertInfo) + oldCerts[i].get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + CertificateValidity oldValidity = (CertificateValidity) + oldCertInfo.get(X509CertInfo.VALIDITY); + Date notAfter = (Date) + oldValidity.get(CertificateValidity.NOT_AFTER); + + // Is the Certificate still valid? + Date now = CMS.getCurrentDate(); + + CMS.debug("RenewalConstraints: cert " + i + " notAfter " + notAfter + " now=" + now); + if (notAfter.before(now)) { + CMS.debug( + "RenewalConstraints: One or more certificates is expired."); + String params[] = { getInstanceName() }; + + setError(req, + CMS.getUserMessage("CMS_POLICY_CANNOT_RENEW_EXPIRED_CERTS", + params), ""); + result = PolicyResult.REJECTED; + break; + } + } + + } catch (Exception e) { + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + confParams.addElement( + PROP_ALLOW_EXPIRED_CERTS + "=" + mAllowExpiredCerts); + confParams.addElement(PROP_RENEWAL_NOT_AFTER + "=" + + mRenewalNotAfter / DAYS_TO_MS_FACTOR); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return defConfParams; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/RenewalValidityConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/RenewalValidityConstraints.java new file mode 100644 index 000000000..0265ff855 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/RenewalValidityConstraints.java @@ -0,0 +1,351 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.util.Date; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IRenewalPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; +import com.netscape.cmsutil.util.Utils; + +/** + * RenewalValidityConstraints is a default rule for Certificate + * Renewal. This policy enforces the no of days before which a + * currently active certificate can be renewed and sets new validity + * period for the renewed certificate starting from the the ending + * period in the old certificate. + * + * The main parameters are: + * + * The renewal leadtime in days: - i.e how many days before the + * expiry of the current certificate can one request the renewal. + * min and max validity duration. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class RenewalValidityConstraints extends APolicyRule + implements IRenewalPolicy, IExtendedPluginInfo { + private long mMinValidity; + private long mMaxValidity; + private long mRenewalInterval; + + private final static String PROP_MIN_VALIDITY = "minValidity"; + private final static String PROP_MAX_VALIDITY = "maxValidity"; + private final static String PROP_RENEWAL_INTERVAL = "renewalInterval"; + public final static int DEF_MIN_VALIDITY = 180; + public final static int DEF_MAX_VALIDITY = 730; + public final static long DEF_RENEWAL_INTERVAL = 15; + public final static long DAYS_TO_MS_FACTOR = 24L * 3600 * 1000; + public static final String CERT_HEADER = "-----BEGIN CERTIFICATE-----\n"; + public static final String CERT_TRAILER = "-----END CERTIFICATE-----\n"; + + private final static Vector<String> defConfParams = new Vector<String>(); + + static { + defConfParams.addElement(PROP_MIN_VALIDITY + "=" + + DEF_MIN_VALIDITY); + defConfParams.addElement(PROP_MAX_VALIDITY + "=" + + DEF_MAX_VALIDITY); + defConfParams.addElement(PROP_RENEWAL_INTERVAL + "=" + + DEF_RENEWAL_INTERVAL); + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_MIN_VALIDITY + + ";number;Specifies the minimum validity period, in days, for renewed certificates.", + PROP_MAX_VALIDITY + + ";number;Specifies the maximum validity period, in days, for renewed certificates.", + PROP_RENEWAL_INTERVAL + + ";number;Specifies how many days before its expiration that a certificate can be renewed.", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-renewalvalidityconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Reject renewal request if the certificate is too far " + + "before it's expiry date" + }; + + return params; + + } + + public RenewalValidityConstraints() { + NAME = "RenewalValidityConstraints"; + DESC = "Enforces minimum and maximum validity and renewal interval for certificate renewal."; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form: + * + * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.minValidity=30 ra.Policy.rule.<ruleName>.maxValidity=180 + * ra.Policy.rule.<ruleName>.renewalInterval=15 ra.Policy.rule.<ruleName>.predicate=ou==Sales + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + + // Get min and max validity in days and onfigure them. + try { + String val = config.getString(PROP_MIN_VALIDITY, null); + + if (val == null) + mMinValidity = DEF_MIN_VALIDITY * DAYS_TO_MS_FACTOR; + else + mMinValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR; + + val = config.getString(PROP_MAX_VALIDITY, null); + if (val == null) + mMaxValidity = DEF_MAX_VALIDITY * DAYS_TO_MS_FACTOR; + else { + mMaxValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR; + } + val = config.getString(PROP_RENEWAL_INTERVAL, null); + if (val == null) + mRenewalInterval = DEF_RENEWAL_INTERVAL * DAYS_TO_MS_FACTOR; + else { + mRenewalInterval = Long.parseLong(val) * DAYS_TO_MS_FACTOR; + } + + // minValidity can't be bigger than maxValidity. + if (mMinValidity > mMaxValidity) { + String params[] = { getInstanceName(), + String.valueOf(mMinValidity / DAYS_TO_MS_FACTOR), + String.valueOf(mMaxValidity / DAYS_TO_MS_FACTOR) }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_RENEWAL_MIN_MAX", params)); + } + + // Renewal interval can't be more than maxValidity. + if (mRenewalInterval > mMaxValidity) { + String params[] = { getInstanceName(), + String.valueOf(mRenewalInterval / DAYS_TO_MS_FACTOR), + String.valueOf(mMaxValidity / DAYS_TO_MS_FACTOR) }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_RENEWAL_INTERVAL", params)); + } + } catch (Exception e) { + // e.printStackTrace(); + String[] params = { getInstanceName(), e.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params)); + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + + PolicyResult result = PolicyResult.ACCEPTED; + + if (agentApproved(req)) + return result; + + try { + // Get the certificate info from the request + X509CertInfo certInfo[] = + req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + // Get the certificates being renwed. + X509CertImpl currentCerts[] = + req.getExtDataInCertArray(IRequest.OLD_CERTS); + + // Both certificate info and current certs should be set + if (certInfo == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + if (currentCerts == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_OLD_CERT", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + if (certInfo.length != currentCerts.length) { + setError(req, CMS.getUserMessage("CMS_POLICY_MISMATCHED_CERTINFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + // Else check if the renewal interval is okay and then + // set the validity. + for (int i = 0; i < certInfo.length; i++) { + X509CertInfo oldCertInfo = (X509CertInfo) + currentCerts[i].get(X509CertImpl.NAME + + "." + X509CertImpl.INFO); + CertificateValidity oldValidity = (CertificateValidity) + oldCertInfo.get(X509CertInfo.VALIDITY); + Date notAfter = (Date) + oldValidity.get(CertificateValidity.NOT_AFTER); + + // Is the Certificate still valid? + Date now = CMS.getCurrentDate(); + + if (notAfter.after(now)) { + // Check if the renewal interval is alright. + long interval = notAfter.getTime() - now.getTime(); + + if (interval > mRenewalInterval) { + setError(req, + CMS.getUserMessage("CMS_POLICY_LONG_RENEWAL_LEAD_TIME", + getInstanceName(), + String.valueOf(mRenewalInterval / DAYS_TO_MS_FACTOR)), ""); + setError(req, + CMS.getUserMessage("CMS_POLICY_EXISTING_CERT_DETAILS", + getInstanceName(), + getCertDetails(req, currentCerts[i])), ""); + + result = PolicyResult.REJECTED; + setDummyValidity(certInfo[i]); + continue; + } + } + + // Else compute new validity. + Date renewedNotBef = notAfter; + Date renewedNotAfter = new Date(notAfter.getTime() + + mMaxValidity); + + // If the new notAfter is within renewal interval days from + // today or already expired, set the notBefore to today. + if (renewedNotAfter.before(now) || + (renewedNotAfter.getTime() - now.getTime()) <= + mRenewalInterval) { + renewedNotBef = now; + renewedNotAfter = new Date(now.getTime() + + mMaxValidity); + } + CertificateValidity newValidity = + new CertificateValidity(renewedNotBef, renewedNotAfter); + + certInfo[i].set(X509CertInfo.VALIDITY, newValidity); + } + } catch (Exception e) { + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + confParams.addElement(PROP_MIN_VALIDITY + "=" + + mMinValidity / DAYS_TO_MS_FACTOR); + confParams.addElement(PROP_MAX_VALIDITY + "=" + + mMaxValidity / DAYS_TO_MS_FACTOR); + confParams.addElement(PROP_RENEWAL_INTERVAL + "=" + + mRenewalInterval / DAYS_TO_MS_FACTOR); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return defConfParams; + } + + // Set dummy validity field so the request will serialize properly + private void setDummyValidity(X509CertInfo certInfo) { + try { + certInfo.set(X509CertInfo.VALIDITY, + new CertificateValidity(CMS.getCurrentDate(), new Date())); + } catch (Exception e) { + } + } + + private String getCertDetails(IRequest req, X509CertImpl cert) { + StringBuffer sb = new StringBuffer(); + + sb.append("\n"); + sb.append("Serial No: " + cert.getSerialNumber().toString(16)); + sb.append("\n"); + sb.append("Validity: " + cert.getNotBefore().toString() + + " - " + cert.getNotAfter().toString()); + sb.append("\n"); + String certType = req.getExtDataInString(IRequest.CERT_TYPE); + + if (certType == null) + certType = IRequest.SERVER_CERT; + if (certType.equals(IRequest.CLIENT_CERT)) { + + /*** + * Take this our - URL formulation hard to do here. + * sb.append("Use the following url with your CA/RA gateway spec to download the certificate."); + * sb.append("\n"); + * sb.append("/query/certImport?op=displayByserial&serialNumber="); + * sb.append(cert.getSerialNumber().toString(16)); + ***/ + sb.append("\n"); + } else { + sb.append("Certificate Content is as follows:"); + sb.append("\n"); + try { + byte[] ba = cert.getEncoded(); + String encodedCert = Utils.base64encode(ba); + + sb.append(CERT_HEADER + encodedCert + CERT_TRAILER); + } catch (Exception e) { + //throw new AssertionException(e.toString()); + } + } + return sb.toString(); + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/RevocationConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/RevocationConstraints.java new file mode 100644 index 000000000..513e199c4 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/RevocationConstraints.java @@ -0,0 +1,215 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.util.Date; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.RevocationReason; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IRevocationPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * Whether to allow revocation of an expired cert. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class RevocationConstraints extends APolicyRule + implements IRevocationPolicy, IExtendedPluginInfo { + private static final String PROP_ALLOW_EXPIRED_CERTS = "allowExpiredCerts"; + private static final String PROP_ALLOW_ON_HOLD = "allowOnHold"; + + private boolean mAllowExpiredCerts = true; + private boolean mAllowOnHold = true; + + private final static Vector<String> defConfParams = new Vector<String>(); + static { + defConfParams.addElement(PROP_ALLOW_EXPIRED_CERTS + "=" + true); + defConfParams.addElement(PROP_ALLOW_ON_HOLD + "=" + true); + } + + public RevocationConstraints() { + NAME = "RevocationConstraints"; + DESC = "Whether to allow revocation of expired certs and on-hold."; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_ALLOW_EXPIRED_CERTS + ";boolean;Allow a user to revoke an already-expired certificate", + PROP_ALLOW_ON_HOLD + ";boolean;Allow a user to set reason to On-Hold", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-revocationconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Allow administrator to decide policy on whether to allow " + + "recovation of expired certificates" + + "and set reason to On-Hold" + + }; + + return params; + + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form: + * + * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.allowExpiredCerts=true + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + // Get min and max validity in days and onfigure them. + try { + mAllowExpiredCerts = + config.getBoolean(PROP_ALLOW_EXPIRED_CERTS, true); + mAllowOnHold = + config.getBoolean(PROP_ALLOW_ON_HOLD, true); + } catch (EBaseException e) { + // never happen. + } + + CMS.debug("RevocationConstraints: allow expired certs " + mAllowExpiredCerts); + CMS.debug("RevocationConstraints: allow on hold " + mAllowOnHold); + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + CMS.debug("RevocationConstraints: apply begins"); + if (req.getExtDataInInteger(IRequest.REVOKED_REASON) == null) { + CMS.debug("RevocationConstraints: apply: no revocationReason found in request"); + return PolicyResult.REJECTED; + } + RevocationReason rr = RevocationReason.fromInt( + req.getExtDataInInteger(IRequest.REVOKED_REASON).intValue()); + + if (!mAllowOnHold && (rr != null)) { + int reason = rr.toInt(); + + if (reason == RevocationReason.CERTIFICATE_HOLD.toInt()) { + String params[] = { getInstanceName() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_NO_ON_HOLD_ALLOWED", params), ""); + return PolicyResult.REJECTED; + } + } + + if (mAllowExpiredCerts) + // nothing to check. + return PolicyResult.ACCEPTED; + + PolicyResult result = PolicyResult.ACCEPTED; + + try { + // Get the certificates being renwed. + X509CertImpl[] oldCerts = + req.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (oldCerts == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_OLD_CERT"), + getInstanceName()); + return PolicyResult.REJECTED; + } + + // check if each cert to be renewed is expired. + for (int i = 0; i < oldCerts.length; i++) { + X509CertInfo oldCertInfo = (X509CertInfo) + oldCerts[i].get( + X509CertImpl.NAME + "." + X509CertImpl.INFO); + CertificateValidity oldValidity = (CertificateValidity) + oldCertInfo.get(X509CertInfo.VALIDITY); + Date notAfter = (Date) + oldValidity.get(CertificateValidity.NOT_AFTER); + + // Is the Certificate still valid? + Date now = CMS.getCurrentDate(); + + if (notAfter.before(now)) { + String params[] = { getInstanceName() }; + + setError(req, + CMS.getUserMessage("CMS_POLICY_CANNOT_REVOKE_EXPIRED_CERTS", + params), ""); + result = PolicyResult.REJECTED; + break; + } + } + + } catch (Exception e) { + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + confParams.addElement( + PROP_ALLOW_EXPIRED_CERTS + "=" + mAllowExpiredCerts); + confParams.addElement( + PROP_ALLOW_ON_HOLD + "=" + mAllowOnHold); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return defConfParams; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/SigningAlgorithmConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/SigningAlgorithmConstraints.java new file mode 100644 index 000000000..8b504eb50 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/SigningAlgorithmConstraints.java @@ -0,0 +1,449 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.util.Locale; +import java.util.StringTokenizer; +import java.util.Vector; + +import netscape.security.x509.AlgorithmId; +import netscape.security.x509.CertificateAlgorithmId; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.IAuthority; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.policy.IPolicyProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * SigningAlgorithmConstraints enforces that only a supported + * signing algorithm be requested. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class SigningAlgorithmConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + private String[] mAllowedAlgs = null; // algs allowed by this policy + static String[] mDefaultAllowedAlgs = null; // default algs allowed by this policy based on CA's key + private String[] mConfigAlgs = null; // algs listed in config file + private boolean winnowedByKey = false; + IAuthority mAuthority = null; + private final static String PROP_ALGORITHMS = "algorithms"; + + private final static Vector<String> defConfParams = new Vector<String>(); + + static { + StringBuffer sb = new StringBuffer(); + sb.append(PROP_ALGORITHMS); + sb.append("="); + int i = 0; + boolean first = true; + + mDefaultAllowedAlgs = new String[AlgorithmId.ALL_SIGNING_ALGORITHMS.length]; + for (i = 0; i < AlgorithmId.ALL_SIGNING_ALGORITHMS.length; i++) { + mDefaultAllowedAlgs[i] = AlgorithmId.ALL_SIGNING_ALGORITHMS[i]; + if (first == true) { + sb.append(AlgorithmId.ALL_SIGNING_ALGORITHMS[i]); + first = false; + } else { + sb.append(","); + sb.append(AlgorithmId.ALL_SIGNING_ALGORITHMS[i]); + } + } + defConfParams.addElement(sb.toString()); + } + + public SigningAlgorithmConstraints() { + NAME = "SigningAlgorithmConstraints"; + DESC = "Enforces Signing Algorithm Constraints."; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=SigningAlgorithmConstraints + * ra.Policy.rule.<ruleName>.algorithms=SHA-1WithRSA, SHA-1WithDSA ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.predicate=ou==Sales + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + mAuthority = (IAuthority) ((IPolicyProcessor) owner).getAuthority(); + + // Get allowed algorithms from config file + if (config != null) { + String algNames = null; + + try { + algNames = config.getString(PROP_ALGORITHMS, null); + } catch (Exception e) { + String[] params = { getInstanceName(), e.toString(), PROP_ALGORITHMS }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_PARAM_CONFIG_ERROR", params)); + } + + if (algNames != null) { + // parse alg names into Vector + StringTokenizer tok = new StringTokenizer(algNames, ","); + Vector<String> algs = new Vector<String>(); + + while (tok.hasMoreTokens()) { + algs.addElement(tok.nextToken().trim()); + } + + // convert to array for speedy traversals during apply() + int itemCount = algs.size(); + + mAllowedAlgs = new String[itemCount]; + for (int i = 0; i < itemCount; i++) { + mAllowedAlgs[i] = (String) algs.elementAt(i); + } + + } + + } + + // these are the algorithms from the config file + mConfigAlgs = mAllowedAlgs; + if (mConfigAlgs == null) { + mConfigAlgs = new String[0]; + } + + if (mAllowedAlgs != null) { + // winnow out unknown algorithms + winnowAlgs(AlgorithmId.ALL_SIGNING_ALGORITHMS, + "CMS_POLICY_UNKNOWN_SIGNING_ALG", true); + } else { + // if nothing was in the config file, allow all known algs + mAllowedAlgs = AlgorithmId.ALL_SIGNING_ALGORITHMS; + } + + // winnow out algorithms that don't make sense for the key + winnowByKey(); + + if (mAllowedAlgs.length == 0) { + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_SIGNALG_NOT_MATCH_CAKEY", NAME)); + } + + } + + /** + * winnow out algorithms that don't make sense for the CA's key + */ + private synchronized void winnowByKey() throws EBaseException { + // only do this successfully once + if (winnowedByKey) { + return; + } + + // don't do this ever for DRM + if (!(mAuthority instanceof ICertAuthority)) { + winnowedByKey = true; + return; + } + + // get list of algorithms allowed for the key + String[] allowedByKey = + ((ICertAuthority) mAuthority).getCASigningAlgorithms(); + + if (allowedByKey != null) { + // don't show algorithms that don't match CA's key in UI. + mDefaultAllowedAlgs = new String[allowedByKey.length]; + for (int i = 0; i < allowedByKey.length; i++) + mDefaultAllowedAlgs[i] = allowedByKey[i]; + // winnow out algorithms that don't match CA's signing key + winnowAlgs(allowedByKey, + "CMS_POLICY_SIGNALG_NOT_MATCH_CAKEY_1", false); + winnowedByKey = true; + } else { + // We don't know the CA's signing algorithms. Maybe we're + // an RA that hasn't talked to the CA yet? Try again later. + } + } + + /** + * Winnows out of mAllowedAlgorithms those algorithms that aren't allowed + * for some reason. + * + * @param allowed An array of allowed algorithms. Only algorithms in this + * list will survive the winnowing process. + * @param reason A string describing the problem with an algorithm + * that is not allowed by this list. Must be a predefined string in PolicyResources. + */ + private void winnowAlgs(String[] allowed, String reason, boolean isError) + throws EBaseException { + int i, j, goodSize; + + // validate the currently-allowed algorithms + Vector<String> goodAlgs = new Vector<String>(); + + for (i = 0; i < mAllowedAlgs.length; i++) { + for (j = 0; j < allowed.length; j++) { + if (mAllowedAlgs[i].equals(allowed[j])) { + goodAlgs.addElement(mAllowedAlgs[i]); + break; + } + } + // if algorithm is not allowed, log a warning + if (j == allowed.length) { + EPolicyException e = new EPolicyException(CMS.getUserMessage(reason, NAME, mAllowedAlgs[i])); + + if (isError) { + log(ILogger.LL_FAILURE, e.toString()); + throw new EPolicyException(CMS.getUserMessage(reason, + NAME, mAllowedAlgs[i])); + } else { + log(ILogger.LL_WARN, e.toString()); + } + } + } + + // convert back into an array + goodSize = goodAlgs.size(); + if (mAllowedAlgs.length != goodSize) { + mAllowedAlgs = new String[goodSize]; + for (i = 0; i < goodSize; i++) { + mAllowedAlgs[i] = (String) goodAlgs.elementAt(i); + } + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + int i, j; + + PolicyResult result = PolicyResult.ACCEPTED; + + try { + + // Get the certificate info from the request + //X509CertInfo certInfo[] = (X509CertInfo[]) + // req.get(IRequest.CERT_INFO); + X509CertInfo certInfo[] = req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + // We need to have a certificate info set + if (certInfo == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + // Else check if the key algorithm is supported. + for (i = 0; i < certInfo.length; i++) { + // make sure our list of allowed algorithms makes + // sense for our key. Do this each time. + if (!winnowedByKey) { + winnowByKey(); + } + + CertificateAlgorithmId certAlgId = (CertificateAlgorithmId) + certInfo[i].get(X509CertInfo.ALGORITHM_ID); + + AlgorithmId algId = (AlgorithmId) + certAlgId.get(CertificateAlgorithmId.ALGORITHM); + String alg = algId.getName(); + + // test against the list of allowed algorithms + for (j = 0; j < mAllowedAlgs.length; j++) { + if (mAllowedAlgs[j].equals(alg)) { + break; + } + } + if (j == mAllowedAlgs.length) { + // if the algor doesn't match the CA's key replace + // it with one that does. + if (mAllowedAlgs[0].equals("SHA1withDSA") || + alg.equals("SHA1withDSA")) { + certInfo[i].set(X509CertInfo.ALGORITHM_ID, + new CertificateAlgorithmId( + AlgorithmId.get(mAllowedAlgs[0]))); + return PolicyResult.ACCEPTED; + } + + // didn't find a match, alg not allowed + setError(req, CMS.getUserMessage("CMS_POLICY_SIGNING_ALG_VIOLATION", + getInstanceName(), alg), ""); + result = PolicyResult.REJECTED; + } + } + } catch (Exception e) { + // e.printStackTrace(); + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", + params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < mConfigAlgs.length; i++) { + sb.append(mConfigAlgs[i]); + sb.append(","); + } + if (sb.length() > 0) + sb.setLength(sb.length() - 1); + confParams.addElement(PROP_ALGORITHMS + "=" + sb.toString()); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + StringBuffer sb = new StringBuffer(); + sb.append(PROP_ALGORITHMS); + sb.append("="); + boolean first = true; + + defConfParams.removeAllElements(); + + for (int i = 0; i < mDefaultAllowedAlgs.length; i++) { + if (first == true) { + sb.append(mDefaultAllowedAlgs[i]); + first = false; + } else { + sb.append(","); + sb.append(mDefaultAllowedAlgs[i]); + } + } + defConfParams.addElement(sb.toString()); + + return defConfParams; + } + + public String[] getExtendedPluginInfo(Locale locale) { + if (!winnowedByKey) { + try { + winnowByKey(); + } catch (Exception e) { + } + } + + String[] params = null; + + String[] params_BOTH = { + PROP_ALGORITHMS + + ";" + + "choice(MD2withRSA\\,MD5withRSA\\,SHA1withRSA\\,SHA256withRSA\\,SHA512withRSA\\,SHA1withDSA," + + + "MD2withRSA\\,MD5withRSA\\,SHA1withRSA\\,SHA1withDSA," + + "MD2withRSA\\,MD5withRSA\\,SHA1withRSA," + + "MD2withRSA\\,SHA1withRSA\\,SHA1withDSA," + + "MD5withRSA\\,SHA1withRSA\\,SHA1withDSA," + + "MD2withRSA\\,MD5withRSA\\,SHA1withDSA," + + "MD2withRSA\\,MD5withRSA," + + "MD2withRSA\\,SHA1withRSA," + + "MD2withRSA\\,SHA1withDSA," + + "MD5withRSA\\,SHA1withRSA," + + "MD5withRSA\\,SHA1withDSA," + + "SHA1withRSA\\,SHA1withDSA," + + "MD2withRSA," + + "MD5withRSA," + + "SHA1withRSA," + + "SHA1withDSA);List of algorithms to restrict the requested signing algorithm " + + "to be one of the algorithms supported by Certificate System", + IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-signingalgconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Restricts the requested signing algorithm to be one of" + + " the algorithms supported by Certificate System" + }; + + String[] params_RSA = { + PROP_ALGORITHMS + ";" + "choice(MD2withRSA\\,MD5withRSA\\,SHA1withRSA," + + "MD2withRSA\\,MD5withRSA," + + "MD2withRSA\\,SHA1withRSA," + + "MD5withRSA\\,SHA1withRSA," + + "MD2withRSA," + + "MD5withRSA," + + "SHA1withRSA);Restrict the requested signing algorithm to be " + + "one of the algorithms supported by Certificate System", + IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-signingalgconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Restricts the requested signing algorithm to be one of" + + " the algorithms supported by Certificate System" + }; + + String[] params_DSA = { + PROP_ALGORITHMS + ";" + "choice(SHA1withDSA);Restrict the requested signing " + + "algorithm to be one of the algorithms supported by Certificate " + + "System", + IExtendedPluginInfo.HELP_TOKEN + ";configuration-policyrules-signingalgconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Restricts the requested signing algorithm to be one of" + + " the algorithms supported by Certificate System" + }; + + switch (mDefaultAllowedAlgs.length) { + case 1: + params = params_DSA; + break; + + case 3: + params = params_RSA; + break; + + case 4: + default: + params = params_BOTH; + break; + + } + + return params; + } + +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/SubCANameConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/SubCANameConstraints.java new file mode 100644 index 000000000..da63f6f24 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/SubCANameConstraints.java @@ -0,0 +1,195 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +import java.util.Locale; +import java.util.Vector; + +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.X500Name; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.policy.IPolicyProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.certsrv.security.ISigningUnit; +import com.netscape.cms.policy.APolicyRule; + +/** + * This simple policy checks the subordinate CA CSR to see + * if it is the same as the local CA. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class SubCANameConstraints extends APolicyRule implements IEnrollmentPolicy, IExtendedPluginInfo { + public ICertificateAuthority mCA = null; + public String mIssuerNameStr = null; + + public SubCANameConstraints() { + NAME = "SubCANameConstraints"; + DESC = "Enforces Subordinate CA name."; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-subcanamecheck", + IExtendedPluginInfo.HELP_TEXT + + ";Checks if subordinate CA request matches the local CA. There are no parameters to change" + }; + + return params; + + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form ra.Policy.rule.<ruleName>.implName=KeyAlgorithmConstraints + * ra.Policy.rule.<ruleName>.algorithms=RSA,DSA ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.predicate=ou==Sales + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + // get CA's public key to create authority key id. + ICertAuthority certAuthority = (ICertAuthority) + ((IPolicyProcessor) owner).getAuthority(); + + if (certAuthority == null) { + // should never get here. + log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER")); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", + "Cannot find the Certificate Manager")); + } + if (!(certAuthority instanceof ICertificateAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER")); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", + "Cannot find the Certificate Manager")); + } + mCA = (ICertificateAuthority) certAuthority; + ISigningUnit su = mCA.getSigningUnit(); + if (su == null || CMS.isPreOpMode()) { + return; + } + + X509CertImpl cert = su.getCertImpl(); + + if (cert == null) + return; + X500Name issuerName = (X500Name) cert.getSubjectDN(); + + if (issuerName == null) + return; + mIssuerNameStr = issuerName.toString(); + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + PolicyResult result = PolicyResult.ACCEPTED; + + try { + + // Get the certificate templates + X509CertInfo[] certInfos = req.getExtDataInCertInfoArray( + IRequest.CERT_INFO); + + if (certInfos == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_NO_CERT_INFO", getInstanceName())); + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", NAME + ":" + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + // retrieve the subject name and check its unqiueness + for (int i = 0; i < certInfos.length; i++) { + CertificateSubjectName subName = (CertificateSubjectName) certInfos[i].get(X509CertInfo.SUBJECT); + + // if there is no name set, set one here. + if (subName == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_NO_SUBJECT_NAME_1", getInstanceName())); + setError(req, CMS.getUserMessage("CMS_POLICY_NO_SUBJECT_NAME", NAME + ":" + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + String certSubjectName = subName.toString(); + + if (certSubjectName.equalsIgnoreCase(mIssuerNameStr)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_SUBJECT_NAME_EXIST_1", mIssuerNameStr)); + setError(req, + CMS.getUserMessage("CMS_POLICY_SUBJECT_NAME_EXIST", NAME + ":" + "Same As Issuer Name " + + mIssuerNameStr), ""); + result = PolicyResult.REJECTED; + } + } + } catch (Exception e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("POLICY_NO_SUBJECT_NAME_1", getInstanceName())); + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", + params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> v = new Vector<String>(); + + return v; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + Vector<String> v = new Vector<String>(); + + return v; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/UniqueSubjectName.java b/base/common/src/com/netscape/cms/policy/constraints/UniqueSubjectName.java new file mode 100644 index 000000000..9afbf7650 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/UniqueSubjectName.java @@ -0,0 +1,33 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cms.policy.constraints; + +/** + * This class is used to help migrate CMS4.1 to CMS4.2. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class UniqueSubjectName extends UniqueSubjectNameConstraints { +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/UniqueSubjectNameConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/UniqueSubjectNameConstraints.java new file mode 100644 index 000000000..8c106800a --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/UniqueSubjectNameConstraints.java @@ -0,0 +1,313 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.io.IOException; +import java.util.Enumeration; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.x509.CertificateExtensions; +import netscape.security.x509.CertificateSubjectName; +import netscape.security.x509.KeyUsageExtension; +import netscape.security.x509.X509CertImpl; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.authority.ICertAuthority; +import com.netscape.certsrv.base.EBaseException; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.ca.ICertificateAuthority; +import com.netscape.certsrv.dbs.certdb.ICertRecord; +import com.netscape.certsrv.logging.ILogger; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.policy.IPolicyProcessor; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * Checks the uniqueness of the subject name. This policy + * can only be used (installed) in Certificate Authority + * subsystem. + * + * This policy can perform pre-agent-approval checking or + * post-agent-approval checking based on configuration + * setting. + * + * In some situations, user may want to have 2 certificates with + * the same subject name. For example, one key for encryption, + * and one for signing. This policy does not deal with this case + * directly. But it can be easily extended to do that. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class UniqueSubjectNameConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + protected static final String PROP_PRE_AGENT_APPROVAL_CHECKING = + "enablePreAgentApprovalChecking"; + protected static final String PROP_KEY_USAGE_EXTENSION_CHECKING = + "enableKeyUsageExtensionChecking"; + + public ICertificateAuthority mCA = null; + + public boolean mPreAgentApprovalChecking = false; + public boolean mKeyUsageExtensionChecking = true; + + public UniqueSubjectNameConstraints() { + NAME = "UniqueSubjectName"; + DESC = "Ensure the uniqueness of the subject name."; + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_PRE_AGENT_APPROVAL_CHECKING + + ";boolean;If checked, check subject name uniqueness BEFORE agent approves, (else checks AFTER approval)", + PROP_KEY_USAGE_EXTENSION_CHECKING + + ";boolean;If checked, allow non-unique subject names if Key Usage Extension differs", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-uniquesubjectname", + IExtendedPluginInfo.HELP_TEXT + + ";Rejects a request if there exists an unrevoked, unexpired " + + "certificate with the same subject name" + }; + + return params; + + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form: + * + * ca.Policy.rule.<ruleName>.implName=UniqueSubjectName ca.Policy.rule.<ruleName>.enable=true + * ca.Policy.rule.<ruleName>.enable=true ca.Policy.rule.<ruleName>.enablePreAgentApprovalChecking=true + * ca.Policy.rule.<ruleName>.enableKeyUsageExtensionChecking=true + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EBaseException { + // get CA's public key to create authority key id. + ICertAuthority certAuthority = (ICertAuthority) + ((IPolicyProcessor) owner).getAuthority(); + + if (certAuthority == null) { + // should never get here. + log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER")); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", + "Cannot find the Certificate Manager or Registration Manager")); + } + if (!(certAuthority instanceof ICertificateAuthority)) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CA_CANT_FIND_MANAGER")); + throw new EBaseException(CMS.getUserMessage("CMS_BASE_INTERNAL_ERROR", + "Cannot find the Certificate Manager")); + } + + mCA = (ICertificateAuthority) certAuthority; + try { + mPreAgentApprovalChecking = + config.getBoolean(PROP_PRE_AGENT_APPROVAL_CHECKING, false); + } catch (EBaseException e) { + } + try { + mKeyUsageExtensionChecking = + config.getBoolean(PROP_KEY_USAGE_EXTENSION_CHECKING, true); + } catch (EBaseException e) { + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + if (!mPreAgentApprovalChecking) { + // post agent approval checking + if (!agentApproved(req)) + return PolicyResult.ACCEPTED; + } + PolicyResult result = PolicyResult.ACCEPTED; + + try { + + // Get the certificate templates + X509CertInfo[] certInfos = req.getExtDataInCertInfoArray( + IRequest.CERT_INFO); + + if (certInfos == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + // retrieve the subject name and check its unqiueness + for (int i = 0; i < certInfos.length; i++) { + CertificateSubjectName subName = (CertificateSubjectName) + certInfos[i].get(X509CertInfo.SUBJECT); + + // if there is no name set, set one here. + if (subName == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_SUBJECT_NAME", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + String certSubjectName = subName.toString(); + String filter = "x509Cert.subject=" + certSubjectName; + // subject name is indexed, so we only use subject name + // in the filter + Enumeration<ICertRecord> matched = + mCA.getCertificateRepository().findCertRecords(filter); + + while (matched.hasMoreElements()) { + ICertRecord rec = matched.nextElement(); + String status = rec.getStatus(); + + if (status.equals(ICertRecord.STATUS_REVOKED) + || status.equals(ICertRecord.STATUS_EXPIRED) + || status.equals(ICertRecord.STATUS_REVOKED_EXPIRED)) { + // accept this only if we have a REVOKED, + // EXPIRED or REVOKED_EXPIRED certificate + continue; + + } + // you already have an VALID or INVALID (not yet valid) certificate + if (mKeyUsageExtensionChecking && agentApproved(req)) { + // This request is agent approved which + // means all requested extensions are finalized + // to the request, + // We will accept duplicated subject name with + // different keyUsage extension if + // keyUsageExtension is different. + if (!sameKeyUsageExtension(rec, certInfos[i])) { + continue; + } + } + + setError(req, CMS.getUserMessage("CMS_POLICY_SUBJECT_NAME_EXIST", + getInstanceName() + " " + certSubjectName), ""); + return PolicyResult.REJECTED; + } + } + } catch (Exception e) { + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", + params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Checks if the key extension in the issued certificate + * is the same as the one in the certificate template. + */ + private boolean sameKeyUsageExtension(ICertRecord rec, + X509CertInfo certInfo) { + X509CertImpl impl = rec.getCertificate(); + boolean bits[] = impl.getKeyUsage(); + + CertificateExtensions extensions = null; + + try { + extensions = (CertificateExtensions) + certInfo.get(X509CertInfo.EXTENSIONS); + } catch (IOException e) { + } catch (java.security.cert.CertificateException e) { + } + KeyUsageExtension ext = null; + + if (extensions == null) { + if (bits != null) + return false; + } else { + try { + ext = (KeyUsageExtension) extensions.get( + KeyUsageExtension.NAME); + } catch (IOException e) { + // extension isn't there. + } + + if (ext == null) { + if (bits != null) + return false; + } else { + boolean[] InfoBits = ext.getBits(); + + if (InfoBits == null) { + if (bits != null) + return false; + } else { + if (bits == null) + return false; + if (InfoBits.length != bits.length) { + return false; + } + for (int i = 0; i < InfoBits.length; i++) { + if (InfoBits[i] != bits[i]) + return false; + } + } + } + } + return true; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + confParams.addElement(PROP_PRE_AGENT_APPROVAL_CHECKING + + "=" + mPreAgentApprovalChecking); + confParams.addElement(PROP_KEY_USAGE_EXTENSION_CHECKING + + "=" + mKeyUsageExtensionChecking); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + Vector<String> defParams = new Vector<String>(); + + defParams.addElement(PROP_PRE_AGENT_APPROVAL_CHECKING + "="); + defParams.addElement(PROP_KEY_USAGE_EXTENSION_CHECKING + "="); + return defParams; + } +} diff --git a/base/common/src/com/netscape/cms/policy/constraints/ValidityConstraints.java b/base/common/src/com/netscape/cms/policy/constraints/ValidityConstraints.java new file mode 100644 index 000000000..0409f3c33 --- /dev/null +++ b/base/common/src/com/netscape/cms/policy/constraints/ValidityConstraints.java @@ -0,0 +1,317 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 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.constraints; + +import java.util.Date; +import java.util.Locale; +import java.util.Vector; + +import netscape.security.x509.CertificateValidity; +import netscape.security.x509.X509CertInfo; + +import com.netscape.certsrv.apps.CMS; +import com.netscape.certsrv.base.IConfigStore; +import com.netscape.certsrv.base.IExtendedPluginInfo; +import com.netscape.certsrv.base.ISubsystem; +import com.netscape.certsrv.policy.EPolicyException; +import com.netscape.certsrv.policy.IEnrollmentPolicy; +import com.netscape.certsrv.request.IRequest; +import com.netscape.certsrv.request.PolicyResult; +import com.netscape.cms.policy.APolicyRule; + +/** + * ValidityConstraints is a default rule for Enrollment and + * Renewal that enforces minimum and maximum validity periods + * and changes them if not met. + * + * Optionally the lead and lag times - i.e how far back into the + * front or back the notBefore date could go in minutes can also + * be specified. + * <P> + * + * <PRE> + * NOTE: The Policy Framework has been replaced by the Profile Framework. + * </PRE> + * <P> + * + * @deprecated + * @version $Revision$, $Date$ + */ +public class ValidityConstraints extends APolicyRule + implements IEnrollmentPolicy, IExtendedPluginInfo { + protected long mMinValidity; + protected long mMaxValidity; + protected long mLeadTime; + protected long mLagTime; + protected long mNotBeforeSkew; + + private final static String PROP_MIN_VALIDITY = "minValidity"; + private final static String PROP_MAX_VALIDITY = "maxValidity"; + private final static String PROP_LEAD_TIME = "leadTime"; + private final static String PROP_LAG_TIME = "lagTime"; + private final static String PROP_NOT_BEFORE_SKEW = "notBeforeSkew"; + public final static int DEF_MIN_VALIDITY = 180; + public final static int DEF_MAX_VALIDITY = 730; + public final static int DEF_LEAD_TIME = 10; + public final static int DEF_LAG_TIME = 10; + public final static int DEF_NOT_BEFORE_SKEW = 5; + public final static long DAYS_TO_MS_FACTOR = 24L * 3600 * 1000; + public final static long MINS_TO_MS_FACTOR = 60L * 1000; + + private final static Vector<String> defConfParams = new Vector<String>(); + + static { + defConfParams.addElement(PROP_MIN_VALIDITY + "=" + + DEF_MIN_VALIDITY); + defConfParams.addElement(PROP_MAX_VALIDITY + "=" + + DEF_MAX_VALIDITY); + defConfParams.addElement(PROP_LEAD_TIME + "=" + + DEF_LEAD_TIME); + defConfParams.addElement(PROP_LAG_TIME + "=" + + DEF_LAG_TIME); + defConfParams.addElement(PROP_NOT_BEFORE_SKEW + "=" + + DEF_NOT_BEFORE_SKEW); + } + + public String[] getExtendedPluginInfo(Locale locale) { + String[] params = { + PROP_MIN_VALIDITY + ";number;Minimum Validity time, in days", + PROP_MAX_VALIDITY + ";number;Maximum Validity time, in days", + PROP_LEAD_TIME + ";number;Number of minutes in the future a request's notBefore can be", + PROP_LAG_TIME + ";number;NOT CURRENTLY IN USE", + PROP_NOT_BEFORE_SKEW + ";number;Number of minutes a cert's notBefore should be in the past", + IExtendedPluginInfo.HELP_TOKEN + + ";configuration-policyrules-validityconstraints", + IExtendedPluginInfo.HELP_TEXT + + ";Ensures that the user's requested validity period is " + + "acceptable. If not specified, as is usually the case, " + + "this policy will set the validity. See RFC 2459." + }; + + return params; + + } + + public ValidityConstraints() { + NAME = "ValidityConstraints"; + DESC = "Enforces minimum and maximum validity constraints."; + } + + /** + * Initializes this policy rule. + * <P> + * + * The entries probably are of the form: + * + * ra.Policy.rule.<ruleName>.implName=ValidityConstraints ra.Policy.rule.<ruleName>.enable=true + * ra.Policy.rule.<ruleName>.minValidity=30 ra.Policy.rule.<ruleName>.maxValidity=180 + * ra.Policy.rule.<ruleName>.predicate=ou==Sales + * + * @param config The config store reference + */ + public void init(ISubsystem owner, IConfigStore config) + throws EPolicyException { + + // Get min and max validity in days and configure them. + try { + String val = config.getString(PROP_MIN_VALIDITY, null); + + if (val == null) + mMinValidity = DEF_MIN_VALIDITY * DAYS_TO_MS_FACTOR; + else + mMinValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR; + + val = config.getString(PROP_MAX_VALIDITY, null); + if (val == null) + mMaxValidity = DEF_MAX_VALIDITY * DAYS_TO_MS_FACTOR; + else + mMaxValidity = Long.parseLong(val) * DAYS_TO_MS_FACTOR; + + val = config.getString(PROP_LEAD_TIME, null); + if (val != null) + mLeadTime = Long.parseLong(val) * MINS_TO_MS_FACTOR; + else + mLeadTime = DEF_LEAD_TIME * MINS_TO_MS_FACTOR; + + val = config.getString(PROP_LAG_TIME, null); + if (val != null) + mLagTime = Long.parseLong(val) * MINS_TO_MS_FACTOR; + else + mLagTime = DEF_LAG_TIME * MINS_TO_MS_FACTOR; + + val = config.getString(PROP_NOT_BEFORE_SKEW, null); + if (val != null) + mNotBeforeSkew = Long.parseLong(val) * MINS_TO_MS_FACTOR; + else + mNotBeforeSkew = DEF_NOT_BEFORE_SKEW * MINS_TO_MS_FACTOR; + } catch (Exception e) { + // e.printStackTrace(); + String[] params = { getInstanceName(), e.toString() }; + + throw new EPolicyException( + CMS.getUserMessage("CMS_POLICY_INVALID_POLICY_CONFIG", params)); + } + } + + /** + * Applies the policy on the given Request. + * <P> + * + * @param req The request on which to apply policy. + * @return The policy result object. + */ + public PolicyResult apply(IRequest req) { + + PolicyResult result = PolicyResult.ACCEPTED; + + try { + // Get the certificate info from the request + //X509CertInfo certInfo[] = (X509CertInfo[]) + // req.get(IRequest.CERT_INFO); + X509CertInfo certInfo[] = req.getExtDataInCertInfoArray(IRequest.CERT_INFO); + + // There should be a certificate info set. + if (certInfo == null) { + setError(req, CMS.getUserMessage("CMS_POLICY_NO_CERT_INFO", + getInstanceName()), ""); + return PolicyResult.REJECTED; + } + + // Else check if validity is within the limit + for (int i = 0; i < certInfo.length; i++) { + CertificateValidity validity = (CertificateValidity) + certInfo[i].get(X509CertInfo.VALIDITY); + + Date notBefore = null, notAfter = null; + + if (validity != null) { + notBefore = (Date) + validity.get(CertificateValidity.NOT_BEFORE); + notAfter = (Date) + validity.get(CertificateValidity.NOT_AFTER); + } + + // If no validity is supplied yet, make one. The default + // validity is supposed to pass the following checks, so + // bypass further checking. + // (date = 0 is hack for serialization) + + if (validity == null || + (notBefore.getTime() == 0 && notAfter.getTime() == 0)) { + certInfo[i].set(X509CertInfo.VALIDITY, + makeDefaultValidity(req)); + continue; + } + + Date now = CMS.getCurrentDate(); + + if (notBefore.getTime() > (now.getTime() + mLeadTime)) { + setError(req, CMS.getUserMessage("CMS_POLICY_INVALID_BEGIN_TIME", + getInstanceName()), ""); + result = PolicyResult.REJECTED; + } + if ((notAfter.getTime() - notBefore.getTime()) > mMaxValidity) { + String params[] = { getInstanceName(), + String.valueOf( + ((notAfter.getTime() - notBefore.getTime()) / DAYS_TO_MS_FACTOR)), + String.valueOf(mMaxValidity / DAYS_TO_MS_FACTOR) }; + + setError(req, CMS.getUserMessage("CMS_POLICY_MORE_THAN_MAX_VALIDITY", params), ""); + result = PolicyResult.REJECTED; + } + if ((notAfter.getTime() - notBefore.getTime()) < mMinValidity) { + String params[] = { getInstanceName(), + String.valueOf( + ((notAfter.getTime() - notBefore.getTime()) / DAYS_TO_MS_FACTOR)), + String.valueOf(mMinValidity / DAYS_TO_MS_FACTOR) }; + + setError(req, CMS.getUserMessage("CMS_POLICY_LESS_THAN_MIN_VALIDITY", params), ""); + result = PolicyResult.REJECTED; + } + } + } catch (Exception e) { + // e.printStackTrace(); + String params[] = { getInstanceName(), e.toString() }; + + setError(req, CMS.getUserMessage("CMS_POLICY_UNEXPECTED_POLICY_ERROR", + params), ""); + result = PolicyResult.REJECTED; + } + return result; + } + + /** + * Return configured parameters for a policy rule instance. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getInstanceParams() { + Vector<String> confParams = new Vector<String>(); + + confParams.addElement(PROP_MIN_VALIDITY + "=" + + mMinValidity / DAYS_TO_MS_FACTOR); + confParams.addElement(PROP_MAX_VALIDITY + "=" + + mMaxValidity / DAYS_TO_MS_FACTOR); + confParams.addElement(PROP_LEAD_TIME + "=" + + mLeadTime / MINS_TO_MS_FACTOR); + confParams.addElement(PROP_LAG_TIME + "=" + + mLagTime / MINS_TO_MS_FACTOR); + confParams.addElement(PROP_NOT_BEFORE_SKEW + "=" + + mNotBeforeSkew / MINS_TO_MS_FACTOR); + return confParams; + } + + /** + * Return default parameters for a policy implementation. + * + * @return nvPairs A Vector of name/value pairs. + */ + public Vector<String> getDefaultParams() { + return defConfParams; + } + + /** + * Create a default validity value for a request + * + * This code can be easily overridden in a derived class, if the + * calculations here aren't accepatble. + * + * TODO: it might be good to base this calculation on the creation + * time of the request. + */ + protected CertificateValidity makeDefaultValidity(IRequest req) { + long now = roundTimeToSecond((CMS.getCurrentDate()).getTime()); + + // We will set the max duration as the default validity. + long notBeforeTime = now - mNotBeforeSkew; + Date notBefore = new Date(notBeforeTime); + Date notAfter = new Date(notBeforeTime + mMaxValidity); + + return new CertificateValidity(notBefore, notAfter); + } + + /** + * convert a millisecond resolution time into one with 1 second + * resolution. Most times in certificates are storage at 1 + * second resolution, so its better if we deal with things at + * that level. + */ + protected long roundTimeToSecond(long input) { + return (input / 1000) * 1000; + } +} |