diff options
author | mharmsen <mharmsen@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2011-10-29 04:43:21 +0000 |
---|---|---|
committer | mharmsen <mharmsen@c9f7a03b-bd48-0410-a16d-cbbf54688b0b> | 2011-10-29 04:43:21 +0000 |
commit | db615a895b644af038308ae71b680f1d93f78f70 (patch) | |
tree | 6d1a4510d625fd4d6afe2848b8de686af74a118a /pki/base/common/src/com/netscape/cmscore/ldap | |
parent | a8a64c7f1dcaf3012fa8d3cd164c890ceb146d0d (diff) | |
download | pki-db615a895b644af038308ae71b680f1d93f78f70.tar.gz pki-db615a895b644af038308ae71b680f1d93f78f70.tar.xz pki-db615a895b644af038308ae71b680f1d93f78f70.zip |
Bugzilla Bug #737761 - Update Dogtag Packages for Fedora 16DOGTAG_9_0_FEDORA_15_16_17_20111028
git-svn-id: svn+ssh://svn.fedorahosted.org/svn/pki/tags/DOGTAG_9_0_FEDORA_15_16_17_20111028@2279 c9f7a03b-bd48-0410-a16d-cbbf54688b0b
Diffstat (limited to 'pki/base/common/src/com/netscape/cmscore/ldap')
10 files changed, 4366 insertions, 0 deletions
diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapAndExpression.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapAndExpression.java new file mode 100644 index 000000000..598ae198b --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapAndExpression.java @@ -0,0 +1,75 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import com.netscape.certsrv.base.IAttrSet; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; + + +/** + * This class represents an expression of the form + * <var1 op val1 AND var2 op va2>. + * + * Expressions are used as predicates for publishing rule selection. + * + * @author mzhao + * @version $Revision$, $Date$ + */ +public class LdapAndExpression implements ILdapExpression { + private ILdapExpression mExp1; + private ILdapExpression mExp2; + public LdapAndExpression(ILdapExpression exp1, ILdapExpression exp2) { + mExp1 = exp1; + mExp2 = exp2; + } + + public boolean evaluate(SessionContext sc) + throws ELdapException { + // If an expression is missing we assume applicability. + if (mExp1 == null && mExp2 == null) + return true; + else if (mExp1 != null && mExp2 != null) + return mExp1.evaluate(sc) && mExp2.evaluate(sc); + else if (mExp1 == null) + return mExp2.evaluate(sc); + else // (if mExp2 == null) + return mExp1.evaluate(sc); + } + + public boolean evaluate(IRequest req) + throws ELdapException { + // If an expression is missing we assume applicability. + if (mExp1 == null && mExp2 == null) + return true; + else if (mExp1 != null && mExp2 != null) + return mExp1.evaluate(req) && mExp2.evaluate(req); + else if (mExp1 == null) + return mExp2.evaluate(req); + else // (if mExp2 == null) + return mExp1.evaluate(req); + } + + public String toString() { + return mExp1.toString() + " AND " + mExp2.toString(); + } +} + diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapConnModule.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapConnModule.java new file mode 100644 index 000000000..273a21c96 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapConnModule.java @@ -0,0 +1,141 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.util.Hashtable; +import java.util.Enumeration; +import java.math.BigInteger; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.authority.*; +import java.security.*; +import java.security.cert.*; +import java.io.IOException; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; + +import com.netscape.cmscore.ldapconn.*; +import com.netscape.cmscore.util.Debug; + + +public class LdapConnModule implements ILdapConnModule { + protected IConfigStore mConfig = null; + protected LdapBoundConnFactory mLdapConnFactory = null; + protected ILogger mLogger = CMS.getLogger(); + private boolean mInited = false; + + /** + * instantiate connection factory. + */ + + public static final String PROP_LDAP = "ldap"; + + public LdapConnModule() { + } + + public LdapConnModule(LdapBoundConnFactory factory) { + mLdapConnFactory = factory; + mInited = true; + } + + protected ISubsystem mPubProcessor; + + public void init(ISubsystem p, + IConfigStore config) + throws EBaseException { + + CMS.debug("LdapConnModule: init called"); + if (mInited) { + CMS.debug("LdapConnModule: already initialized. return."); + return; + } + CMS.debug("LdapConnModule: init begins"); + + mPubProcessor = p; + mConfig = config; + /* + mLdapConnFactory = new LdapBoundConnFactory(); + mLdapConnFactory.init(mConfig.getSubStore("ldap")); + */ + + // support publishing dirsrv with different pwd than internaldb + IConfigStore ldap = mConfig.getSubStore("ldap"); + + IConfigStore ldapconn = ldap.getSubStore( + ILdapBoundConnFactory.PROP_LDAPCONNINFO); + IConfigStore authinfo = ldap.getSubStore( + ILdapBoundConnFactory.PROP_LDAPAUTHINFO); + ILdapConnInfo connInfo = + CMS.getLdapConnInfo(ldapconn); + LdapAuthInfo authInfo = + new LdapAuthInfo(authinfo, ldapconn.getString("host"), + ldapconn.getInteger("port"), connInfo.getSecure()); + + int minConns = mConfig.getInteger(ILdapBoundConnFactory.PROP_MINCONNS, 3); + int maxConns = mConfig.getInteger(ILdapBoundConnFactory.PROP_MAXCONNS, 15); + // must get authInfo from the config, don't default to internaldb!!! + + CMS.debug("Creating LdapBoundConnFactory for LdapConnModule."); + mLdapConnFactory = + new LdapBoundConnFactory(minConns, maxConns, (LdapConnInfo)connInfo, authInfo); + + mInited = true; + + CMS.debug("LdapConnModule: init ends"); + } + + /** + * Returns the internal ldap connection factory. + * This can be useful to get a ldap connection to the + * ldap publishing directory without having to get it again from the + * config file. Note that this means sharing a ldap connection pool + * with the ldap publishing module so be sure to return connections to pool. + * Use ILdapConnFactory.getConn() to get a Ldap connection to the ldap + * publishing directory. + * Use ILdapConnFactory.returnConn() to return the connection. + * + * @see com.netscape.certsrv.ldap.ILdapBoundConnFactory + * @see com.netscape.certsrv.ldap.ILdapConnFactory + */ + public ILdapConnFactory getLdapConnFactory() { + return mLdapConnFactory; + } + + public LDAPConnection getConn() throws ELdapException { + return mLdapConnFactory.getConn(); + } + + public void returnConn(LDAPConnection conn) throws ELdapException { + mLdapConnFactory.returnConn(conn); + } + + public void log(int level, String msg) { + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_LDAP, level, + "LdapPublishModule: " + msg); + } + +} + diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapOrExpression.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapOrExpression.java new file mode 100644 index 000000000..ae0e1a310 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapOrExpression.java @@ -0,0 +1,79 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; + + +/** + * This class represents an Or expression of the form + * (var1 op val1 OR var2 op val2). + * + * Expressions are used as predicates for publishing rule selection. + * + * @author mzhao + * @version $Revision$, $Date$ + */ +public class LdapOrExpression implements ILdapExpression { + private ILdapExpression mExp1; + private ILdapExpression mExp2; + public LdapOrExpression(ILdapExpression exp1, ILdapExpression exp2) { + mExp1 = exp1; + mExp2 = exp2; + } + + public boolean evaluate(SessionContext sc) + throws ELdapException { + if (mExp1 == null && mExp2 == null) + return true; + else if (mExp1 != null && mExp2 != null) + return mExp1.evaluate(sc) || mExp2.evaluate(sc); + else if (mExp1 != null && mExp2 == null) + return mExp1.evaluate(sc); + else // (mExp1 == null && mExp2 != null) + return mExp2.evaluate(sc); + } + + public boolean evaluate(IRequest req) + throws ELdapException { + if (mExp1 == null && mExp2 == null) + return true; + else if (mExp1 != null && mExp2 != null) + return mExp1.evaluate(req) || mExp2.evaluate(req); + else if (mExp1 != null && mExp2 == null) + return mExp1.evaluate(req); + else // (mExp1 == null && mExp2 != null) + return mExp2.evaluate(req); + } + + public String toString() { + if (mExp1 == null && mExp2 == null) + return ""; + else if (mExp1 != null && mExp2 != null) + return mExp1.toString() + " OR " + mExp2.toString(); + else if (mExp1 != null && mExp2 == null) + return mExp1.toString(); + else // (mExp1 == null && mExp2 != null) + return mExp2.toString(); + } +} + diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapPredicateParser.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPredicateParser.java new file mode 100644 index 000000000..b8e62d896 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPredicateParser.java @@ -0,0 +1,374 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.util.*; +import java.io.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; +import com.netscape.cmscore.util.*; +import com.netscape.certsrv.apps.*; + + +/** + * Default implementation of predicate parser. + * + * Limitations: + * + * 1. Currently parentheses are not suported. + * 2. Only ==, != <, >, <= and >= operators are supported. + * 3. The only boolean operators supported are AND and OR. AND takes precedence + * over OR. Example: a AND b OR e OR c AND d + * is treated as (a AND b) OR e OR (c AND d) + * 4. If this is n't adequate, roll your own. + * + * @author mzhao + * @version $Revision$, $Date$ + */ +public class LdapPredicateParser { + public static final int OP_AND = 1; + public static final int OP_OR = 2; + public static final int EXPRESSION = 0; + + public static final String AND = "AND"; + public static final String OR = "OR"; + + private static final char COMMA = ','; + + /** + * Parse the predicate expression and return a vector of expressions. + * + * @param predicateExp The predicate expression as read from the config file. + * @return expVector The vector of expressions. + */ + public static ILdapExpression parse(String predicateExpression) + throws ELdapException { + if (predicateExpression == null || + predicateExpression.length() == 0) + return null; + PredicateTokenizer pt = new PredicateTokenizer(predicateExpression); + + if (pt == null || !pt.hasMoreTokens()) + return null; + + // The first token cannot be an operator. We are not dealing with + // reverse-polish notation. + String token = pt.nextToken(); + boolean opANDSeen; + boolean opORSeen; + + if (getOP(token) != EXPRESSION) { + if (Debug.ON) + Debug.trace("Malformed expression: " + predicateExpression); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_BAD_LDAP_EXPRESSION", predicateExpression)); + } + ILdapExpression current = parseExpression(token); + boolean malformed = false; + Vector expSet = new Vector(); + int prevType = EXPRESSION; + + while (pt.hasMoreTokens()) { + token = pt.nextToken(); + int curType = getOP(token); + + if ((prevType != EXPRESSION && curType != EXPRESSION) || + (prevType == EXPRESSION && curType == EXPRESSION)) { + malformed = true; + break; + } + + // If an operator seen skip to the next token + if (curType != EXPRESSION) { + prevType = curType; + continue; + } + + // If the previous type was an OR token, add the current expression to + // the expression set; + if (prevType == OP_OR) { + expSet.addElement(current); + current = parseExpression(token); + prevType = curType; + continue; + } + + // If the previous type was an AND token, make an AND expression + if (prevType == OP_AND) { + current = new LdapAndExpression(current, parseExpression(token)); + prevType = curType; + } + } + if (malformed) { + if (Debug.ON) + Debug.trace("Malformed expression: " + predicateExpression); + throw new ELdapException( + CMS.getUserMessage("CMS_LDAP_BAD_LDAP_EXPRESSION", + predicateExpression)); + } + + // Form an LdapOrExpression + if (current != null) + expSet.addElement(current); + + int size = expSet.size(); + + if (size == 0) + return null; + LdapOrExpression orExp = new + LdapOrExpression((ILdapExpression) expSet.elementAt(0), null); + + for (int i = 1; i < size; i++) + orExp = new LdapOrExpression(orExp, + (ILdapExpression) expSet.elementAt(i)); + return orExp; + } + + private static int getOP(String token) { + if (token.equalsIgnoreCase(AND)) + return OP_AND; + else if (token.equalsIgnoreCase(OR)) + return OP_OR; + else + return EXPRESSION; + } + + private static ILdapExpression parseExpression(String input) + throws ELdapException { + // If the expression has multiple parts separated by commas + // we need to construct an AND expression. Else we will return a + // simple expression. + int commaIndex = input.indexOf(COMMA); + + if (commaIndex < 0) + return LdapSimpleExpression.parse(input); + int currentIndex = 0; + Vector expVector = new Vector(); + + while (commaIndex > 0) { + LdapSimpleExpression exp = (LdapSimpleExpression) + LdapSimpleExpression.parse(input.substring(currentIndex, + commaIndex)); + + expVector.addElement(exp); + currentIndex = commaIndex + 1; + commaIndex = input.indexOf(COMMA, currentIndex); + } + if (currentIndex < (input.length() - 1)) { + LdapSimpleExpression exp = (LdapSimpleExpression) + LdapSimpleExpression.parse(input.substring(currentIndex)); + + expVector.addElement(exp); + } + + int size = expVector.size(); + LdapSimpleExpression exp1 = (LdapSimpleExpression) expVector.elementAt(0); + LdapSimpleExpression exp2 = (LdapSimpleExpression) expVector.elementAt(1); + LdapAndExpression andExp = new LdapAndExpression(exp1, exp2); + + for (int i = 2; i < size; i++) { + andExp = new LdapAndExpression(andExp, (LdapSimpleExpression) expVector.elementAt(i)); + } + return andExp; + } + + public static void main(String[] args) { + + /** + AttributeSet req = new AttributeSet(); + try + { + req.set("ou", "people"); + req.set("cn", "John Doe"); + req.set("uid", "jdoes"); + req.set("o", "airius.com"); + req.set("certtype", "client"); + req.set("request", "issuance"); + req.set("id", new Integer(10)); + req.set("dualcerts", new Boolean(true)); + + Vector v = new Vector(); + v.addElement("one"); + v.addElement("two"); + v.addElement("three"); + req.set("count", v); + } + catch (Exception e){e.printStackTrace();} + String[] array = { "ou == people AND certtype == client", + "ou == servergroup AND certtype == server", + "uid == jdoes, ou==people, o==airius.com OR ou == people AND certType == client OR certType == server AND cn == needles.mcom.com", + }; + for (int i = 0; i < array.length; i++) + { + System.out.println(); + System.out.println("String: " + array[i]); + ILdapExpression exp = null; + try + { + exp = parse(array[i]); + if (exp != null) + { + System.out.println("Parsed Expression: " + exp); + boolean result = exp.evaluate(req); + System.out.println("Result: " + result); + } + } + catch (Exception e) {e.printStackTrace(); } + } + + + try + { + BufferedReader rdr = new BufferedReader( + new FileReader(args[0])); + String line; + while((line=rdr.readLine()) != null) + { + System.out.println(); + System.out.println("Line Read: " + line); + ILdapExpression exp = null; + try + { + exp = parse(line); + if (exp != null) + { + System.out.println(exp); + boolean result = exp.evaluate(req); + System.out.println("Result: " + result); + } + + }catch (Exception e){e.printStackTrace();} + } + } + catch (Exception e){e.printStackTrace(); } + + **/ + } + +} + + +class PredicateTokenizer { + String input; + int currentIndex; + int endOfString; + String nextToken; + boolean first; + + public PredicateTokenizer(String predString) { + input = predString; + currentIndex = 0; + nextToken = null; + } + + public boolean hasMoreTokens() { + return (currentIndex != -1); + } + + public String nextToken() { + if (nextToken != null) { + String toReturn = nextToken; + + nextToken = null; + return toReturn; + } + + int andIndex = input.indexOf(" AND", currentIndex); + + if (andIndex < 0) + andIndex = input.indexOf(" and", currentIndex); + int orIndex = input.indexOf(" OR", currentIndex); + + if (orIndex < 0) + orIndex = input.indexOf(" or", currentIndex); + String toReturn = null; + + if (andIndex == -1 && orIndex == -1) { + if (currentIndex == 0) { + currentIndex = -1; + toReturn = input; + } else { + int temp = currentIndex; + + currentIndex = -1; + toReturn = input.substring(temp); + } + } else if (andIndex >= 0 && (andIndex < orIndex || orIndex == -1)) { + if (currentIndex != andIndex) { + toReturn = input.substring(currentIndex, andIndex); + nextToken = input.substring(andIndex + 1, andIndex + 4); + currentIndex = andIndex + 4; + } else { + toReturn = "AND"; + currentIndex += 4; + } + } else if (orIndex >= 0 && (orIndex < andIndex || andIndex == -1)) { + if (currentIndex != orIndex) { + toReturn = input.substring(currentIndex, orIndex); + nextToken = input.substring(orIndex + 1, orIndex + 3); + currentIndex = orIndex + 3; + } else { + toReturn = "OR"; + currentIndex += 3; + } + } else { + // Cannot happen; Assert here. + toReturn = null; + System.out.println("We shouldn't be here!"); + } + if (toReturn == null) + return null; + else { + String trimmed = toReturn.trim(); + + if (trimmed == null || trimmed.length() == 0) + return nextToken(); + else + return trimmed; + } + } +} + + +class AttributeSet implements IAttrSet { + Hashtable ht = new Hashtable(); + public AttributeSet() { + } + + public void delete(String name) + throws EBaseException { + Object ob = ht.get(name); + + ht.remove(ob); + } + + public Object get(String name) + throws EBaseException { + return ht.get(name); + } + + public void set(String name, Object ob) + throws EBaseException { + ht.put(name, ob); + } + + public Enumeration getElements() { + return ht.elements(); + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapPublishModule.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPublishModule.java new file mode 100644 index 000000000..0afd0ed43 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapPublishModule.java @@ -0,0 +1,796 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.util.Hashtable; +import java.util.Enumeration; +import java.math.BigInteger; + +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.cmscore.util.Debug; +import com.netscape.certsrv.ldap.*; +import com.netscape.cmscore.ldapconn.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.authority.*; +import java.security.*; +import java.security.cert.*; +import java.io.IOException; +import netscape.ldap.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.cmscore.dbs.*; +import com.netscape.certsrv.apps.*; + + +public class LdapPublishModule implements ILdapPublishModule { + protected IConfigStore mConfig = null; + protected LdapBoundConnFactory mLdapConnFactory = null; + protected ILogger mLogger = CMS.getLogger(); + private boolean mInited = false; + protected ICertAuthority mAuthority = null; + + /** + * hashtable of cert types to cert mappers and publishers. + * cert types are client, server, ca, subca, ra, crl, etc. + * XXX the cert types need to be consistently used. + * for each, the mapper may be null, in which case the full subject + * name is used to map the cert. + * for crl, if the mapper is null the ca mapper is used. if that + * is null, the full issuer name is used. + * XXX if we support crl issuing points the issuing point should be used + * to publish the crl. + * When publishers are null, the certs are not published. + */ + protected Hashtable mMappers = new Hashtable(); + + /** + * handlers for request types (events) + * values implement IRequestListener + */ + protected Hashtable mEventHandlers = new Hashtable(); + + /** + * instantiate connection factory. + */ + public static final String ATTR_LDAPPUBLISH_STATUS = "LdapPublishStatus"; + public static final String PROP_LDAP = "ldap"; + public static final String PROP_MAPPER = "mapper"; + public static final String PROP_PUBLISHER = "publisher"; + public static final String PROP_CLASS = "class"; + public static final String PROP_TYPE = "type"; + public static final String PROP_TYPE_CA = "ca"; + public static final String PROP_TYPE_CLIENT = "client"; + public static final String PROP_TYPE_CRL = "crl"; + + public LdapPublishModule() { + } + + public void init(ISubsystem sub, IConfigStore config) throws EBaseException + { + } + + public void set(String name, String val) + { + } + + public LdapPublishModule(LdapBoundConnFactory factory) { + mLdapConnFactory = factory; + mInited = true; + } + + protected IPublisherProcessor mPubProcessor; + + public void init(ICertAuthority authority, IPublisherProcessor p, + IConfigStore config) + throws EBaseException { + if (mInited) + return; + + mAuthority = authority; + mPubProcessor = p; + mConfig = config; + mLdapConnFactory = new LdapBoundConnFactory(); + mLdapConnFactory.init(mConfig.getSubStore("ldap")); + + // initMappers(config); + initHandlers(); + + mAuthority.registerRequestListener(this); + } + + public void init(ICertAuthority authority, IConfigStore config) + throws EBaseException { + if (mInited) + return; + + mAuthority = authority; + mConfig = config; + mLdapConnFactory = new LdapBoundConnFactory(); + mLdapConnFactory.init(mConfig.getSubStore("ldap")); + + initMappers(config); + initHandlers(); + + mAuthority.registerRequestListener(this); + } + + /** + * Returns the internal ldap connection factory. + * This can be useful to get a ldap connection to the + * ldap publishing directory without having to get it again from the + * config file. Note that this means sharing a ldap connection pool + * with the ldap publishing module so be sure to return connections to pool. + * Use ILdapConnFactory.getConn() to get a Ldap connection to the ldap + * publishing directory. + * Use ILdapConnFactory.returnConn() to return the connection. + * + * @see com.netscape.certsrv.ldap.ILdapBoundConnFactory + * @see com.netscape.certsrv.ldap.ILdapConnFactory + */ + public ILdapConnFactory getLdapConnFactory() { + return mLdapConnFactory; + } + + /** + * Returns the connection factory to the publishing directory. + * Must return the connection once you return + */ + + protected LdapMappers getMappers(String certType) { + LdapMappers mappers = null; + + if (certType == null) { + mappers = (LdapMappers) mMappers.get(PROP_TYPE_CLIENT); + } else { + mappers = (LdapMappers) mMappers.get(certType); + } + return mappers; + } + + protected void initMappers(IConfigStore config) + throws EBaseException { + IConfigStore types = mConfig.getSubStore(PROP_TYPE); + + if (types == null || types.size() <= 0) { + // nothing configured. + if (Debug.ON) + System.out.println("No ldap publishing configurations."); + return; + } + Enumeration substores = types.getSubStoreNames(); + + while (substores.hasMoreElements()) { + String certType = (String) substores.nextElement(); + IConfigStore current = types.getSubStore(certType); + + if (current == null || current.size() <= 0) { + CMS.debug( + "No ldap publish configuration for " + certType + " found."); + continue; + } + ILdapPlugin mapper = null, publisher = null; + IConfigStore mapperConf = null, publisherConf = null; + String mapperClassName = null, publisherClassName = null; + + try { + mapperConf = current.getSubStore(PROP_MAPPER); + mapperClassName = mapperConf.getString(PROP_CLASS, null); + if (mapperClassName != null && mapperClassName.length() > 0) { + CMS.debug( + "mapper " + mapperClassName + " for " + certType); + mapper = (ILdapPlugin) + Class.forName(mapperClassName).newInstance(); + mapper.init(mapperConf); + } + publisherConf = current.getSubStore(PROP_PUBLISHER); + publisherClassName = publisherConf.getString(PROP_CLASS, null); + if (publisherClassName != null && + publisherClassName.length() > 0) { + CMS.debug( + "publisher " + publisherClassName + " for " + certType); + publisher = (ILdapPlugin) + Class.forName(publisherClassName).newInstance(); + publisher.init(publisherConf); + } + mMappers.put(certType, new LdapMappers(mapper, publisher)); + } catch (ClassNotFoundException e) { + String missingClass = mapperClassName + + ((publisherClassName == null) ? "" : + (" or " + publisherClassName)); + + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_FIND_CLASS", missingClass)); + throw new ELdapException( + CMS.getUserMessage("CMS_LDAP_CLASS_NOT_FOUND", missingClass)); + } catch (InstantiationException e) { + String badInstance = mapperClassName + + ((publisherClassName == null) ? "" : + (" or " + publisherClassName)); + + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_INST_CLASS", + badInstance ,certType)); + throw new ELdapException( + CMS.getUserMessage("CMS_LDAP_INSTANTIATING_CLASS_FAILED", badInstance)); + } catch (IllegalAccessException e) { + String badInstance = mapperClassName + + ((publisherClassName == null) ? "" : + (" or " + publisherClassName)); + + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_INSUFFICIENT_CREDENTIALS", badInstance, certType)); + throw new ELdapException( + CMS.getUserMessage("CMS_LDAP_INSUFFICIENT_CREDENTIALS", certType)); + } catch (EBaseException e) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_INIT_ERROR", certType, e.toString())); + throw e; + } + } + mInited = true; + } + + protected void initHandlers() { + mEventHandlers.put(IRequest.ENROLLMENT_REQUEST, + new HandleEnrollment(this)); + mEventHandlers.put(IRequest.RENEWAL_REQUEST, + new HandleRenewal(this)); + mEventHandlers.put(IRequest.REVOCATION_REQUEST, + new HandleRevocation(this)); + mEventHandlers.put(IRequest.UNREVOCATION_REQUEST, + new HandleUnrevocation(this)); + } + + public void accept(IRequest r) { + String type = r.getRequestType(); + boolean error = false; + + IRequestListener handler = (IRequestListener) mEventHandlers.get(type); + + if (handler == null) { + CMS.debug( + "Nothing to publish for request type " + type); + return; + } + handler.accept(r); + } + + public void publish(String certType, X509Certificate cert) + throws ELdapException { + // get mapper and publisher for cert type. + LdapMappers mappers = getMappers(certType); + + if (mappers == null || mappers.publisher == null) { + CMS.debug("publisher for " + certType + " is null"); + return; + } + publish((ILdapMapper) mappers.mapper, + (ILdapPublisher) mappers.publisher, cert); + + // set the ldap published flag. + setPublishedFlag(cert.getSerialNumber(), true); + } + + public void unpublish(String certType, X509Certificate cert) + throws ELdapException { + // get mapper and publisher for cert type. + LdapMappers mappers = getMappers(certType); + + if (mappers == null || mappers.publisher == null) { + CMS.debug("publisher for " + certType + " is null"); + return; + } + unpublish((ILdapMapper) mappers.mapper, + (ILdapPublisher) mappers.publisher, cert); + + // set the ldap published flag. + setPublishedFlag(cert.getSerialNumber(), false); + } + + /** + * set published flag - true when published, false when unpublished. + * not exist means not published. + */ + public void setPublishedFlag(BigInteger serialNo, boolean published) { + if (!(mAuthority instanceof ICertificateAuthority)) + return; + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + + try { + ICertificateRepository certdb = (ICertificateRepository) ca.getCertificateRepository(); + ICertRecord certRec = (ICertRecord) certdb.readCertificateRecord(serialNo); + MetaInfo metaInfo = certRec.getMetaInfo(); + + if (metaInfo == null) { + metaInfo = new MetaInfo(); + } + metaInfo.set( + CertRecord.META_LDAPPUBLISH, String.valueOf(published)); + ModificationSet modSet = new ModificationSet(); + + modSet.add(ICertRecord.ATTR_META_INFO, + Modification.MOD_REPLACE, metaInfo); + certdb.modifyCertificateRecord(serialNo, modSet); + } catch (EBaseException e) { + // not fatal. just log warning. + log(ILogger.LL_WARN, + "Cannot mark cert 0x" + serialNo.toString(16) + " published as " + published + + " in the ldap directory. Cert Record not found. Error: " + + e.getMessage()); + } + } + + public LDAPConnection getConn() throws ELdapException { + return mLdapConnFactory.getConn(); + } + + public void returnConn(LDAPConnection conn) throws ELdapException { + mLdapConnFactory.returnConn(conn); + } + + public void publish(ILdapMapper mapper, ILdapPublisher publisher, + X509Certificate cert) + throws ELdapException { + LDAPConnection conn = null; + + try { + String dirdn = null; + String result = null; + + conn = mLdapConnFactory.getConn(); + if (mapper == null) { // use the cert's subject name exactly + dirdn = cert.getSubjectDN().toString(); + CMS.debug( + "no mapper found. Using subject name exactly." + + cert.getSubjectDN()); + } else { + result = mapper.map(conn, cert); + dirdn = result; + if (dirdn == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_PUBLISH_NOT_MATCH", + cert.getSerialNumber().toString(16), + cert.getSubjectDN().toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", + cert.getSubjectDN().toString())); + } + } + publisher.publish(conn, dirdn, cert); + } finally { + if (conn != null) { + mLdapConnFactory.returnConn(conn); + } + } + } + + public void unpublish(ILdapMapper mapper, ILdapPublisher publisher, + X509Certificate cert) + throws ELdapException { + LDAPConnection conn = null; + + try { + String dirdn = null; + String result = null; + + conn = mLdapConnFactory.getConn(); + if (mapper == null) { // use the cert's subject name exactly + dirdn = cert.getSubjectDN().toString(); + } else { + result = mapper.map(conn, cert); + dirdn = result; + if (dirdn == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_PUBLISH_NOT_MATCH", + cert.getSerialNumber().toString(16), + cert.getSubjectDN().toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", + cert.getSubjectDN().toString())); + } + } + publisher.unpublish(conn, dirdn, cert); + } finally { + if (conn != null) { + mLdapConnFactory.returnConn(conn); + } + } + } + + /** + * publishes a crl by mapping the issuer name in the crl to an entry + * and publishing it there. entry must be a certificate authority. + */ + public void publish(X509CRLImpl crl) + throws ELdapException { + ILdapCrlMapper mapper = null; + ILdapPublisher publisher = null; + + LdapMappers mappers = getMappers(PROP_TYPE_CRL); + + if (mappers == null || mappers.publisher == null) { + CMS.debug("publisher for crl is null"); + return; + } + + LDAPConnection conn = null; + String dn = null; + + try { + String result = null; + + conn = mLdapConnFactory.getConn(); + if (mappers.mapper == null) { + dn = ((X500Name) crl.getIssuerDN()).toLdapDNString(); + } else { + result = ((ILdapMapper) mappers.mapper).map(conn, crl); + dn = result; + if (dn == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_CRL_NOT_MATCH")); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", + crl.getIssuerDN().toString())); + } + } + ((ILdapPublisher) mappers.publisher).publish(conn, dn, crl); + } catch (ELdapException e) { + //e.printStackTrace(); + CMS.debug( + "Error publishing CRL to " + dn + ": " + e); + throw e; + } catch (IOException e) { + CMS.debug("Error publishing CRL to " + dn + ": " + e); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_GET_ISSUER_FROM_CRL_FAILED", (String) "")); + } finally { + if (conn != null) { + mLdapConnFactory.returnConn(conn); + } + } + } + + /** + * publishes a crl by mapping the issuer name in the crl to an entry + * and publishing it there. entry must be a certificate authority. + */ + public void publish(String dn, X509CRL crl) + throws ELdapException { + LdapMappers mappers = getMappers(PROP_TYPE_CRL); + + if (mappers == null || mappers.publisher == null) { + CMS.debug("publisher for crl is null"); + return; + } + + LDAPConnection conn = null; + + try { + conn = mLdapConnFactory.getConn(); + ((ILdapPublisher) mappers.publisher).publish(conn, dn, crl); + } catch (ELdapException e) { + CMS.debug( + "Error publishing CRL to " + dn + ": " + e.toString()); + throw e; + } finally { + if (conn != null) { + mLdapConnFactory.returnConn(conn); + } + } + } + + public void log(int level, String msg) { + mLogger.log(ILogger.EV_SYSTEM, null, ILogger.S_LDAP, level, + "LdapPublishModule: " + msg); + } + +} + + +class LdapMappers { + public LdapMappers(ILdapPlugin aMapper, ILdapPlugin aPublisher) { + mapper = aMapper; + publisher = aPublisher; + } + public ILdapPlugin mapper = null; + public ILdapPlugin publisher = null; +} + + +class HandleEnrollment implements IRequestListener { + LdapPublishModule mModule = null; + + public HandleEnrollment(LdapPublishModule module) { + mModule = module; + } + + public void set(String name, String val) + { + } + + public void init(ISubsystem sub, IConfigStore config) throws EBaseException + { + } + + public void accept(IRequest r) { + CMS.debug( + "handling publishing for enrollment request id " + + r.getRequestId()); + + // in case it's not meant for us + if (r.getExtDataInInteger(IRequest.RESULT) == null) + return; + + // check if request failed. + if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) { + CMS.debug("Request errored. " + + "Nothing to publish for enrollment request id " + + r.getRequestId()); + return; + } + CMS.debug("Checking publishing for request " + + r.getRequestId()); + // check if issued certs is set. + X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (certs == null || certs.length == 0 || certs[0] == null) { + CMS.debug( + "No certs to publish for request id " + r.getRequestId()); + return; + } + + // get mapper and publisher for client certs. + LdapMappers mappers = + mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT); + + if (mappers == null || mappers.publisher == null) { + CMS.debug( + "In publishing: No publisher for type " + + LdapPublishModule.PROP_TYPE_CLIENT); + return; + } + + // publish + Integer results[] = new Integer[certs.length]; + X509CertImpl cert; + + for (int i = 0; i < certs.length; i++) { + try { + if (certs[i] == null) + continue; + mModule.publish((ILdapMapper) mappers.mapper, + (ILdapPublisher) mappers.publisher, certs[i]); + results[i] = IRequest.RES_SUCCESS; + CMS.debug( + "Published cert serial no 0x" + certs[i].getSerialNumber().toString(16)); + mModule.setPublishedFlag(certs[i].getSerialNumber(), true); + } catch (ELdapException e) { + mModule.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH", + certs[i].getSerialNumber().toString(16),e.toString())); + results[i] = IRequest.RES_ERROR; + } + r.setExtData("ldapPublishStatus", results); + } + } +} + + +class HandleRenewal implements IRequestListener { + private LdapPublishModule mModule = null; + public HandleRenewal(LdapPublishModule module) { + mModule = module; + } + + public void init(ISubsystem sub, IConfigStore config) throws EBaseException + { + } + + public void set(String name, String val) + { + } + + public void accept(IRequest r) { + // Note we do not remove old certs from directory during renewal + X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (certs == null || certs.length == 0) { + CMS.debug("no certs to publish for renewal " + + "request " + r.getRequestId()); + return; + } + Integer results[] = new Integer[certs.length]; + X509CertImpl cert = null; + + // get mapper and publisher for cert type. + LdapMappers mappers = + mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT); + + if (mappers == null || mappers.publisher == null) { + CMS.debug( + "publisher for " + LdapPublishModule.PROP_TYPE_CLIENT + " is null"); + return; + } + + boolean error = false; + + for (int i = 0; i < certs.length; i++) { + cert = (X509CertImpl) certs[i]; + if (cert == null) + continue; // there was an error issuing this cert. + try { + mModule.publish((ILdapMapper) mappers.mapper, + (ILdapPublisher) mappers.publisher, cert); + results[i] = IRequest.RES_SUCCESS; + mModule.log(ILogger.LL_INFO, + "Published cert serial no 0x" + cert.getSerialNumber().toString(16)); + } catch (ELdapException e) { + error = true; + mModule.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH", + cert.getSerialNumber().toString(16), e.getMessage())); + results[i] = IRequest.RES_ERROR; + } + } + r.setExtData("ldapPublishStatus", results); + r.setExtData("ldapPublishOverAllStatus", + (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS)); + } +} + + +class HandleRevocation implements IRequestListener { + private LdapPublishModule mModule = null; + public HandleRevocation(LdapPublishModule module) { + mModule = module; + } + + public void init(ISubsystem sub, IConfigStore config) throws EBaseException + { + } + + public void set(String name, String val) + { + } + + public void accept(IRequest r) { + CMS.debug( + "Handle publishing for revoke request id " + r.getRequestId()); + + // get fields in request. + X509CertImpl[] revcerts = r.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (revcerts == null || revcerts.length == 0 || revcerts[0] == null) { + // no certs in revoke. + CMS.debug( + "Nothing to unpublish for revocation " + + "request " + r.getRequestId()); + return; + } + + // get mapper and publisher for cert type. + LdapMappers mappers = + mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT); + + if (mappers == null || mappers.publisher == null) { + CMS.debug( + "publisher for " + LdapPublishModule.PROP_TYPE_CLIENT + " is null"); + return; + } + + boolean error = false; + Integer results[] = new Integer[revcerts.length]; + + for (int i = 0; i < revcerts.length; i++) { + X509CertImpl cert = revcerts[i]; + + results[i] = IRequest.RES_ERROR; + try { + mModule.unpublish((ILdapMapper) mappers.mapper, + (ILdapPublisher) mappers.publisher, cert); + results[i] = IRequest.RES_SUCCESS; + CMS.debug( + "Unpublished cert serial no 0x" + cert.getSerialNumber().toString(16)); + } catch (ELdapException e) { + error = true; + mModule.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_UNPUBLISH", + cert.getSerialNumber().toString(16), e.getMessage())); + } catch (EBaseException e) { + error = true; + mModule.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND", + cert.getSerialNumber().toString(16), e.getMessage())); + } + } + r.setExtData("ldapPublishStatus", results); + r.setExtData("ldapPublishOverAllStatus", + (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS)); + } +} + + +class HandleUnrevocation implements IRequestListener { + private LdapPublishModule mModule = null; + public HandleUnrevocation(LdapPublishModule module) { + mModule = module; + } + + public void set(String name, String val) + { + } + public void init(ISubsystem sub, IConfigStore config) throws EBaseException + { + } + + public void accept(IRequest r) { + CMS.debug( + "Handle publishing for unrevoke request id " + r.getRequestId()); + + // get fields in request. + X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (certs == null || certs.length == 0 || certs[0] == null) { + // no certs in unrevoke. + CMS.debug( + "Nothing to publish for unrevocation " + + "request " + r.getRequestId()); + return; + } + + // get mapper and publisher for cert type. + LdapMappers mappers = + mModule.getMappers(LdapPublishModule.PROP_TYPE_CLIENT); + + if (mappers == null || mappers.publisher == null) { + CMS.debug( + "publisher for " + LdapPublishModule.PROP_TYPE_CLIENT + " is null"); + return; + } + + boolean error = false; + Integer results[] = new Integer[certs.length]; + + for (int i = 0; i < certs.length; i++) { + results[i] = IRequest.RES_ERROR; + try { + mModule.publish((ILdapMapper) mappers.mapper, + (ILdapPublisher) mappers.publisher, certs[i]); + results[i] = IRequest.RES_SUCCESS; + CMS.debug( + "Unpublished cert serial no 0x" + certs[i].getSerialNumber().toString(16)); + } catch (ELdapException e) { + error = true; + mModule.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_UNPUBLISH", + certs[i].getSerialNumber().toString(16), e.getMessage())); + } catch (EBaseException e) { + error = true; + mModule.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND", + certs[i].getSerialNumber().toString(16), e.getMessage())); + } + } + r.setExtData("ldapPublishStatus", results); + r.setExtData("ldapPublishOverAllStatus", + (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS)); + } + +} + diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapRequestListener.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRequestListener.java new file mode 100644 index 000000000..d467bd957 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRequestListener.java @@ -0,0 +1,531 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.util.Hashtable; +import java.util.Enumeration; +import java.math.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.profile.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.publish.*; +import java.security.cert.*; +import java.io.IOException; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.ca.*; +import com.netscape.cmscore.dbs.*; +import com.netscape.cmscore.util.*; + + +public class LdapRequestListener implements IRequestListener { + private boolean mInited = false; + + /** + * handlers for request types (events) + * each handler implement IRequestListener + */ + private Hashtable mRequestListeners = new Hashtable(); + + private IPublisherProcessor mPublisherProcessor = null; + + public LdapRequestListener() { + } + + public void set(String name, String val) + { + } + + public void init(ISubsystem sys, IConfigStore config) throws EBaseException { + if (mInited) return; + + mPublisherProcessor = (IPublisherProcessor)sys; + + mRequestListeners.put(IRequest.ENROLLMENT_REQUEST, + new LdapEnrollmentListener(mPublisherProcessor)); + mRequestListeners.put(IRequest.RENEWAL_REQUEST, + new LdapRenewalListener(mPublisherProcessor)); + mRequestListeners.put(IRequest.REVOCATION_REQUEST, + new LdapRevocationListener(mPublisherProcessor)); + mRequestListeners.put(IRequest.UNREVOCATION_REQUEST, + new LdapUnrevocationListener(mPublisherProcessor)); + mInited = true; + } + + public PublishObject getPublishObject(IRequest r) { + String type = r.getRequestType(); + PublishObject obj = new PublishObject(); + + if (type.equals(IRequest.ENROLLMENT_REQUEST)) { + // in case it's not meant for us + if (r.getExtDataInInteger(IRequest.RESULT) == null) + return null; + + // check if request failed. + if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) { + CMS.debug("Request errored. " + + "Nothing to publish for enrollment request id " + + r.getRequestId()); + return null; + } + CMS.debug("Checking publishing for request " + + r.getRequestId()); + // check if issued certs is set. + X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (certs == null || certs.length == 0 || certs[0] == null) { + CMS.debug( + "No certs to publish for request id " + + r.getRequestId()); + return null; + } + obj.setCerts(certs); + return obj; + } else if (type.equals(IRequest.RENEWAL_REQUEST)) { + // Note we do not remove old certs from directory during renewal + X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (certs == null || certs.length == 0) { + CMS.debug("no certs to publish for renewal " + + "request " + r.getRequestId()); + return null; + } + obj.setCerts(certs); + return obj; + } else if (type.equals(IRequest.REVOCATION_REQUEST)) { + X509CertImpl[] revcerts = r.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (revcerts == null || revcerts.length == 0 || revcerts[0] == null) { + // no certs in revoke. + CMS.debug( + "Nothing to unpublish for revocation " + + "request " + r.getRequestId()); + return null; + } + obj.setCerts(revcerts); + return obj; + } else if (type.equals(IRequest.UNREVOCATION_REQUEST)) { + X509CertImpl[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (certs == null || certs.length == 0 || certs[0] == null) { + // no certs in unrevoke. + CMS.debug( + "Nothing to publish for unrevocation " + + "request " + r.getRequestId()); + return null; + } + obj.setCerts(certs); + return obj; + } else { + CMS.debug("Request errored. " + + "Nothing to publish for request id " + + r.getRequestId()); + return null; + } + + } + + public void accept(IRequest r) { + String type = r.getRequestType(); + + IRequestListener handler = (IRequestListener) mRequestListeners.get(type); + + if (handler == null) { + CMS.debug( + "Nothing to publish for request type " + type); + return; + } + handler.accept(r); + } + +} + + +class LdapEnrollmentListener implements IRequestListener { + IPublisherProcessor mProcessor = null; + + public LdapEnrollmentListener(IPublisherProcessor processor) { + mProcessor = processor; + } + + public void init(ISubsystem sys, IConfigStore config) throws EBaseException { + } + + public void set(String name, String val) + { + } + + public void accept(IRequest r) { + CMS.debug( + "LdapRequestListener handling publishing for enrollment request id " + + r.getRequestId()); + + String profileId = r.getExtDataInString("profileId"); + + if (profileId == null) { + // in case it's not meant for us + if (r.getExtDataInInteger(IRequest.RESULT) == null) + return; + + // check if request failed. + if ((r.getExtDataInInteger(IRequest.RESULT)).equals(IRequest.RES_ERROR)) { + CMS.debug("Request errored. " + + "Nothing to publish for enrollment request id " + + r.getRequestId()); + return; + } + } + CMS.debug("Checking publishing for request " + + r.getRequestId()); + // check if issued certs is set. + Certificate[] certs = null; + if (profileId == null) { + certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + } else { + certs = new Certificate[1]; + certs[0] = r.getExtDataInCert(IEnrollProfile.REQUEST_ISSUED_CERT); + } + + if (certs == null || certs.length == 0 || certs[0] == null) { + CMS.debug( + "No certs to publish for request id " + r.getRequestId()); + return; + } + + if (certs[0] instanceof X509CertImpl) + acceptX509(r, certs); + } + + public void acceptX509(IRequest r, Certificate[] certs) { + Integer results[] = new Integer[certs.length]; + boolean error = false; + + for (int i = 0; i < certs.length; i++) { + X509CertImpl xcert = (X509CertImpl) certs[i]; + + if (xcert == null) + continue; + try { + mProcessor.publishCert(xcert, r); + + results[i] = IRequest.RES_SUCCESS; + CMS.debug( + "acceptX509: Published cert serial no 0x" + + xcert.getSerialNumber().toString(16)); + //mProcessor.setPublishedFlag(xcert.getSerialNumber(), true); + } catch (ELdapException e) { + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH", + xcert.getSerialNumber().toString(16), e.toString())); + results[i] = IRequest.RES_ERROR; + error = true; + } + } + r.setExtData("ldapPublishStatus", results); + r.setExtData("ldapPublishOverAllStatus", + (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS)); + } +} + + +class LdapRenewalListener implements IRequestListener { + private IPublisherProcessor mProcessor = null; + + public LdapRenewalListener(IPublisherProcessor processor) { + mProcessor = processor; + } + public void init(ISubsystem sys, IConfigStore config) throws EBaseException { + } + + public void set(String name, String val) + { + } + + public void accept(IRequest r) { + // Note we do not remove old certs from directory during renewal + Certificate[] certs = r.getExtDataInCertArray(IRequest.ISSUED_CERTS); + + if (certs == null || certs.length == 0) { + CMS.debug("no certs to publish for renewal " + + "request " + r.getRequestId()); + return; + } + + if (certs[0] instanceof X509CertImpl) + acceptX509(r, certs); + } + + public void acceptX509(IRequest r, Certificate[] certs) { + X509CertImpl cert = null; + + Integer results[] = new Integer[certs.length]; + boolean error = false; + + for (int i = 0; i < certs.length; i++) { + cert = (X509CertImpl) certs[i]; + if (cert == null) + continue; // there was an error issuing this cert. + try { + mProcessor.publishCert(cert, r); + results[i] = IRequest.RES_SUCCESS; + mProcessor.log(ILogger.LL_INFO, + "Published cert serial no 0x" + + cert.getSerialNumber().toString(16)); + } catch (ELdapException e) { + error = true; + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH", + cert.getSerialNumber().toString(16), e.toString())); + results[i] = IRequest.RES_ERROR; + } + } + r.setExtData("ldapPublishStatus", results); + r.setExtData("ldapPublishOverAllStatus", + (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS)); + } +} + + +class LdapRevocationListener implements IRequestListener { + private IPublisherProcessor mProcessor = null; + + public LdapRevocationListener(IPublisherProcessor processor) { + mProcessor = processor; + } + public void init(ISubsystem sys, IConfigStore config) throws EBaseException { + } + + public void set(String name, String val) + { + } + + public void accept(IRequest r) { + CMS.debug( + "Handle publishing for revoke request id " + r.getRequestId()); + + // get fields in request. + Certificate[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (certs == null || certs.length == 0 || certs[0] == null) { + // no certs in revoke. + CMS.debug( + "Nothing to unpublish for revocation " + + "request " + r.getRequestId()); + return; + } + + if (certs[0] instanceof X509CertImpl) + acceptX509(r, certs); + } + + public void acceptX509(IRequest r, Certificate[] revcerts) { + boolean error = false; + Integer results[] = new Integer[revcerts.length]; + + error = false; + for (int i = 0; i < revcerts.length; i++) { + X509CertImpl cert = (X509CertImpl) revcerts[i]; + + results[i] = IRequest.RES_ERROR; + try { + // We need the enrollment request to sort out predicate + BigInteger serial = cert.getSerialNumber(); + ICertRecord certRecord = null; + IAuthority auth = (IAuthority)mProcessor.getAuthority(); + + if (auth == null || + !(auth instanceof ICertificateAuthority)) { + mProcessor.log(ILogger.LL_WARN, + "Trying to get a certificate from non certificate authority."); + } else { + ICertificateRepository certdb = + (ICertificateRepository) ((ICertificateAuthority) auth).getCertificateRepository(); + + if (certdb == null) { + mProcessor.log(ILogger.LL_WARN, "Cert DB is null for " + auth); + } else { + try { + certRecord = (ICertRecord) certdb.readCertificateRecord(serial); + } catch (EBaseException e) { + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_GET_CERT_RECORD", + serial.toString(16), e.toString())); + } + } + } + + MetaInfo metaInfo = null; + String ridString = null; + + if (certRecord != null) + metaInfo = + (MetaInfo) certRecord.get(ICertRecord.ATTR_META_INFO); + if (metaInfo == null) { + mProcessor.log(ILogger.LL_FAILURE, + "failed getting CertRecord.ATTR_META_INFO for cert serial number 0x" + + serial.toString(16)); + } else { + ridString = (String) metaInfo.get(ICertRecord.META_REQUEST_ID); + } + + IRequest req = null; + + if (ridString != null) { + RequestId rid = new RequestId(ridString); + + req = auth.getRequestQueue().findRequest(rid); + } + mProcessor.unpublishCert(cert, req); + results[i] = IRequest.RES_SUCCESS; + CMS.debug( + "Unpublished cert serial no 0x" + + cert.getSerialNumber().toString(16)); + } catch (ELdapException e) { + error = true; + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_UNPUBLISH", + cert.getSerialNumber().toString(16), e.toString())); + } catch (EBaseException e) { + error = true; + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND", + cert.getSerialNumber().toString(16), e.toString())); + } + } + r.setExtData("ldapPublishStatus", results); + r.setExtData("ldapPublishOverAllStatus", + (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS)); + } +} + + +class LdapUnrevocationListener implements IRequestListener { + private IPublisherProcessor mProcessor = null; + + public LdapUnrevocationListener(IPublisherProcessor processor) { + mProcessor = processor; + } + public void init(ISubsystem sys, IConfigStore config) throws EBaseException { + } + public void set(String name, String val) + { + } + + public void accept(IRequest r) { + CMS.debug( + "Handle publishing for unrevoke request id " + r.getRequestId()); + + // get fields in request. + Certificate[] certs = r.getExtDataInCertArray(IRequest.OLD_CERTS); + + if (certs == null || certs.length == 0 || certs[0] == null) { + // no certs in unrevoke. + CMS.debug( + "Nothing to publish for unrevocation " + + "request " + r.getRequestId()); + return; + } + + if (certs[0] instanceof X509CertImpl) + acceptX509(r, certs); + } + + public void acceptX509(IRequest r, Certificate[] certs) { + boolean error = false; + Integer results[] = new Integer[certs.length]; + X509CertImpl xcert = null; + + for (int i = 0; i < certs.length; i++) { + results[i] = IRequest.RES_ERROR; + xcert = (X509CertImpl) certs[i]; + try { + // We need the enrollment request to sort out predicate + BigInteger serial = xcert.getSerialNumber(); + ICertRecord certRecord = null; + IAuthority auth = (IAuthority)mProcessor.getAuthority(); + + if (auth == null || + !(auth instanceof ICertificateAuthority)) { + mProcessor.log(ILogger.LL_WARN, + "Trying to get a certificate from non certificate authority."); + } else { + ICertificateRepository certdb = (ICertificateRepository) + ((ICertificateAuthority) auth).getCertificateRepository(); + + if (certdb == null) { + mProcessor.log(ILogger.LL_WARN, "Cert DB is null for " + auth); + } else { + try { + certRecord = (ICertRecord) certdb.readCertificateRecord(serial); + } catch (EBaseException e) { + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_GET_CERT_RECORD", serial.toString(16), e.toString())); + } + } + } + + MetaInfo metaInfo = null; + String ridString = null; + + if (certRecord != null) + metaInfo = + (MetaInfo) certRecord.get(CertRecord.ATTR_META_INFO); + if (metaInfo == null) { + mProcessor.log(ILogger.LL_FAILURE, + "Failed getting CertRecord.ATTR_META_INFO for cert serial number 0x" + + serial.toString(16)); + } else { + ridString = (String) metaInfo.get(CertRecord.META_REQUEST_ID); + } + + IRequest req = null; + + if (ridString != null) { + RequestId rid = new RequestId(ridString); + + req = auth.getRequestQueue().findRequest(rid); + } + mProcessor.publishCert(xcert, req); + results[i] = IRequest.RES_SUCCESS; + CMS.debug( + "Published cert serial no 0x" + + xcert.getSerialNumber().toString(16)); + } catch (ELdapException e) { + error = true; + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_PUBLISH", + xcert.getSerialNumber().toString(16), e.toString())); + } catch (EBaseException e) { + error = true; + mProcessor.log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_CERT_NOT_FIND", + xcert.getSerialNumber().toString(16), e.toString())); + } + } + r.setExtData("ldapPublishStatus", results); + r.setExtData("ldapPublishOverAllStatus", + (error == true ? IRequest.RES_ERROR : IRequest.RES_SUCCESS)); + } +} + diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapRule.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRule.java new file mode 100644 index 000000000..d3872740e --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapRule.java @@ -0,0 +1,297 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.util.*; +import netscape.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; +import com.netscape.cmscore.util.*; + + +/** + * The publishing rule that links mapper and publisher together. + */ +public class LdapRule implements ILdapRule, IExtendedPluginInfo { + public final static String NOMAPPER = "<NONE>"; + + private IConfigStore mConfig = null; + protected ILdapExpression mFilterExp = null; + private String mInstanceName = null; + + private IPublisherProcessor mProcessor = null; + + private static String[] epi_params = null; // extendedpluginInfo + + public IConfigStore getConfigStore() { + return mConfig; + } + + public String[] getExtendedPluginInfo(Locale locale) { + //dont know why it's null here. + //if (mProcessor == null) System.out.println("p null"); + + if (Debug.ON) { + Debug.trace("LdapRule: getExtendedPluginInfo() - returning epi_params:"); + for (int i = 0; i < epi_params.length; i++) { + Debug.trace("[" + i + "] " + epi_params[i]); + } + } + return epi_params; + } + + public void init(IPublisherProcessor processor, IConfigStore config) throws EBaseException { + mConfig = config; + + mProcessor = processor; + Enumeration mappers = mProcessor.getMapperInsts().keys(); + Enumeration publishers = mProcessor.getPublisherInsts().keys(); + + String map = NOMAPPER; + + for (; mappers.hasMoreElements();) { + String name = (String) mappers.nextElement(); + + map = map + "," + name; + } + String publish = ""; + + for (; publishers.hasMoreElements();) { + String name = (String) publishers.nextElement(); + + publish = publish + "," + name; + } + + epi_params = new String[] { + "type;choice(cacert,crl, certs);The publishing object type", + "mapper;choice(" + map + ");Use the mapper to find the ldap dn \nto publish the certificate or crl", + "publisher;choice(" + publish + ");Use the publisher to publish the certificate or crl a directory etc", + "enable;boolean;Enable this publishing rule", + "predicate;string;Filter describing when this publishing rule shoule be used" + }; + + // Read the predicate expression if any associated + // with the rule + String exp = config.getString(IPublisherProcessor.PROP_PREDICATE, null); + + if (exp != null) + exp = exp.trim(); + if (exp != null && exp.length() > 0) { + ILdapExpression filterExp = LdapPredicateParser.parse(exp); + + setPredicate(filterExp); + } + //if (mProcessor == null) System.out.println("null"); + + } + + /** + * The init method in ILdapPlugin + * It can not set set mapper,publisher choice for console dynamicly + * Should not use this method to init. + */ + public void init(IConfigStore config) throws EBaseException { + mConfig = config; + + epi_params = new String[] { + "type;choice(cacert, crl, certs);The publishing object type", + "mapper;choice(null,LdapUserCertMap,LdapServerCertMap,LdapCrlMap,LdapCaCertMap);Use the mapper to find the ldap dn to publish the certificate or crl", + "publisher;choice(LdapUserCertPublisher,LdapServerCertPublisher,LdapCrlPublisher,LdapCaCertPublisher);Use the publisher to publish the certificate or crl a directory etc", + "enable;boolean;", + "predicate;string;" + }; + + // Read the predicate expression if any associated + // with the rule + String exp = config.getString(IPublisherProcessor.PROP_PREDICATE, null); + + if (exp != null) + exp = exp.trim(); + if (exp != null && exp.length() > 0) { + ILdapExpression filterExp = LdapPredicateParser.parse(exp); + + setPredicate(filterExp); + } + + } + + /** + * Returns the implementation name. + */ + public String getImplName() { + return "LdapRule"; + } + + /** + * Returns the description of the ldap publisher. + */ + public String getDescription() { + return "LdapRule"; + } + + /** + * Set the instance name + */ + public void setInstanceName(String insName) { + mInstanceName = insName; + } + + /** + * Returns the instance name + */ + public String getInstanceName() { + return mInstanceName; + } + + /** + * Returns the current instance parameters. + */ + public Vector getInstanceParams() { + //if (mProcessor == null) System.out.println("xxxxnull"); + //dont know why the processor was null in getExtendedPluginInfo() + Enumeration mappers = mProcessor.getMapperInsts().keys(); + Enumeration publishers = mProcessor.getPublisherInsts().keys(); + String map = NOMAPPER; + + for (; mappers.hasMoreElements();) { + String name = (String) mappers.nextElement(); + + map = map + "," + name; + } + String publish = ""; + + for (; publishers.hasMoreElements();) { + String name = (String) publishers.nextElement(); + + publish = publish + "," + name; + } + + /* + mExtendedPluginInfo = new NameValuePairs(); + mExtendedPluginInfo.add("type","choice(client,server,objSignClient,smime,ca,crl);The publishing object type"); + mExtendedPluginInfo.add("mapper","choice("+map+");Use the mapper to find the ldap dn \nto publish the certificate or crl"); + mExtendedPluginInfo.add("publisher","choice("+publish+");Use the publisher to publish the certificate or crl a directory etc"); + mExtendedPluginInfo.add("enable","boolean;"); + mExtendedPluginInfo.add("predicate","string;"); + */ + + Vector v = new Vector(); + + try { + v.addElement(IPublisherProcessor.PROP_TYPE + "=" + + mConfig.getString(IPublisherProcessor.PROP_TYPE, "")); + v.addElement(IPublisherProcessor.PROP_PREDICATE + "=" + + mConfig.getString(IPublisherProcessor.PROP_PREDICATE, + "")); + v.addElement(IPublisherProcessor.PROP_ENABLE + "=" + + mConfig.getString(IPublisherProcessor.PROP_ENABLE, + "")); + v.addElement(IPublisherProcessor.PROP_MAPPER + "=" + + mConfig.getString(IPublisherProcessor.PROP_MAPPER, + "")); + v.addElement(IPublisherProcessor.PROP_PUBLISHER + "=" + + mConfig.getString(IPublisherProcessor.PROP_PUBLISHER, + "")); + } catch (EBaseException e) { + } + return v; + } + + /** + * Sets a predicate expression for rule matching. + * <P> + * + * @param exp The predicate expression for the rule. + */ + public void setPredicate(ILdapExpression exp) { + mFilterExp = exp; + } + + /** + * Returns the predicate expression for the rule. + * <P> + * + * @return The predicate expression for the rule. + */ + public ILdapExpression getPredicate() { + return mFilterExp; + } + + public String getMapper() { + try { + String map = + mConfig.getString(IPublisherProcessor.PROP_MAPPER, ""); + + if (map != null) + map = map.trim(); + if (map == null || map.equals("")) + return null; + else if (map.equals(NOMAPPER)) + return null; + else + return map; + } catch (EBaseException e) { + } + return null; + } + + public String getPublisher() { + try { + return mConfig.getString(IPublisherProcessor.PROP_PUBLISHER, ""); + } catch (EBaseException e) { + } + return null; + } + + public String getType() { + try { + return mConfig.getString(IPublisherProcessor.PROP_TYPE, ""); + } catch (EBaseException e) { + } + return null; + } + + public boolean enabled() { + try { + boolean enable = + mConfig.getBoolean(IPublisherProcessor.PROP_ENABLE, false); + + //System.out.println(enable); + return enable; + } catch (EBaseException e) { + } + return false; + } + + /** + * Returns the initial default parameters. + */ + public Vector getDefaultParams() { + Vector v = new Vector(); + + v.addElement(IPublisherProcessor.PROP_TYPE + "="); + v.addElement(IPublisherProcessor.PROP_PREDICATE + "="); + v.addElement(IPublisherProcessor.PROP_ENABLE + "=true"); + v.addElement(IPublisherProcessor.PROP_MAPPER + "="); + v.addElement(IPublisherProcessor.PROP_PUBLISHER + "="); + return v; + } +} diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java b/pki/base/common/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java new file mode 100644 index 000000000..d3646c7b8 --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/LdapSimpleExpression.java @@ -0,0 +1,475 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.util.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; +import com.netscape.certsrv.apps.*; +import com.netscape.cmscore.util.*; + + +/** + * This class represents an expression of the form var = val, + * var != val, var < val, var > val, var <= val, var >= val. + * + * Expressions are used as predicates for publishing rule selection. + * + * @author mzhao + * @version $Revision$, $Date$ + */ +public class LdapSimpleExpression implements ILdapExpression { + private String mPfx; + private String mVar; + private String mVal; + private String mPartialMatch; + private int mOp; + private boolean hasWildCard; + public static final char WILDCARD_CHAR = '*'; + + // This is just for indicating a null expression. + public static LdapSimpleExpression NULL_EXPRESSION = new LdapSimpleExpression("null", OP_EQUAL, "null"); + + public static ILdapExpression parse(String input) + throws ELdapException { + // Get the index of operator + // Debug.trace("LdapSimpleExpression::input: " + input); + String var = null; + int op = -1; + String val = null; + + // XXX - Kanda - Need to change this parsing code eventually. + ExpressionComps comps = parseForEquality(input); + + if (comps == null) + comps = parseForInEquality(input); + if (comps == null) + comps = parseForGE(input); + if (comps == null) + comps = parseForLE(input); + if (comps == null) + comps = parseForGT(input); + if (comps == null) + comps = parseForLT(input); + if (comps == null) + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_BAD_LDAP_EXPRESSION", input)); + + String pfx = null; + String rawVar = comps.getAttr(); + int dotIdx = rawVar.indexOf('.'); + + if (dotIdx != -1) { + pfx = rawVar.substring(0, dotIdx).trim(); + var = rawVar.substring(dotIdx + 1).trim(); + } else { + var = rawVar; + } + op = comps.getOp(); + val = comps.getVal(); + return new LdapSimpleExpression(pfx, var, op, val); + } + + public LdapSimpleExpression(String var, int op, String val) { + this(null, var, op, val); + } + + public LdapSimpleExpression(String prefix, String var, int op, String val) { + // Assert that op has to be either ILdapExpression.OP_EQUAL or + // ILdapExpression.OP_NEQUAL. + // If val or var is null throw an exception! + mPfx = prefix; + mVar = var; + mOp = op; + mVal = val; + int firstIndex; + + if ((firstIndex = mVal.indexOf(WILDCARD_CHAR)) >= 0) { + hasWildCard = true; + int nextIndex = mVal.indexOf(WILDCARD_CHAR, firstIndex + 1); + + if (nextIndex == -1) { + if (firstIndex == 0) + mPartialMatch = mVal.substring(1); + else + mPartialMatch = mVal.substring(0, firstIndex); + } else + mPartialMatch = mVal.substring(firstIndex + 1, nextIndex); + } else + hasWildCard = false; + } + + public boolean evaluate(SessionContext sc) + throws ELdapException { + Object givenVal; + + try { + // Try exact case first. + givenVal = (String) sc.get(mVar); + }catch (Exception e) { + givenVal = (String) null; + } + + // It is kind of a problem here if all letters are in + // lowercase or in upperCase - for example in the case + // of directory attributes. + if (givenVal == null) { + try { + givenVal = (String) sc.get(mVar.toLowerCase()); + }catch (Exception e) { + givenVal = (String) null; + } + } + + if (givenVal == null) { + try { + givenVal = (String) sc.get(mVar.toUpperCase()); + }catch (Exception e) { + givenVal = (String) null; + } + } + + // Debug.trace("mVar: " + mVar + ",Given Value: " + givenVal + ", Value to compare with: " + mVal); + boolean result = false; + + result = matchValue(givenVal); + + return result; + + } + + public boolean evaluate(IRequest req) + throws ELdapException { + boolean result = false; + // mPfx and mVar are looked up case-indendently + if (mPfx != null) { + result = matchValue(req.getExtDataInString(mPfx, mVar)); + } else { + result = matchValue(req.getExtDataInString(mVar)); + } + return result; + } + + private boolean matchVector(Vector value) + throws ELdapException { + boolean result = false; + Enumeration e = (Enumeration) value.elements(); + + for (; e.hasMoreElements();) { + result = matchValue(e.nextElement()); + if (result) + break; + } + return result; + } + + private boolean matchStringArray(String[] value) + throws ELdapException { + boolean result = false; + + for (int i = 0; i < value.length; i++) { + result = matchValue((Object) value[i]); + if (result) + break; + } + return result; + } + + private boolean matchValue(Object value) + throws ELdapException { + boolean result; + + // There is nothing to compare with! + if (value == null) + return false; + + if (value instanceof String) + result = matchStringValue((String) value); + else if (value instanceof Integer) + result = matchIntegerValue((Integer) value); + else if (value instanceof Boolean) + result = matchBooleanValue((Boolean) value); + else if (value instanceof Vector) + result = matchVector((Vector) value); + else if (value instanceof String[]) + result = matchStringArray((String[]) value); + else + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INVALID_ATTR_VALUE", + value.getClass().getName())); + return result; + } + + private boolean matchStringValue(String givenVal) + throws ELdapException { + boolean result; + + switch (mOp) { + case OP_EQUAL: + if (hasWildCard) + result = (givenVal.indexOf(mPartialMatch) >= 0); + else + result = givenVal.equalsIgnoreCase(mVal); + break; + + case OP_NEQUAL: + if (hasWildCard) + result = (givenVal.indexOf(mPartialMatch) < 0); + else + result = !givenVal.equalsIgnoreCase(mVal); + break; + + case OP_LT: + result = (givenVal.compareTo(mVal) < 0); + break; + + case OP_GT: + result = (givenVal.compareTo(mVal) > 0); + break; + + case OP_GE: + result = (givenVal.compareTo(mVal) >= 0); + break; + + case OP_LE: + result = (givenVal.compareTo(mVal) >= 0); + break; + + default: + throw new AssertionException("Invalid operation code"); + } + return result; + } + + private boolean matchIntegerValue(Integer intVal) + throws ELdapException { + boolean result; + int storedVal; + int givenVal = intVal.intValue(); + + try { + storedVal = new Integer(mVal).intValue(); + } catch (Exception e) { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INVALID_ATTR_VALUE", mVal)); + + } + switch (mOp) { + case OP_EQUAL: + result = (givenVal == storedVal); + break; + + case OP_NEQUAL: + result = (givenVal != storedVal); + break; + + case OP_LT: + result = (givenVal < storedVal); + break; + + case OP_GT: + result = (givenVal > storedVal); + break; + + case OP_GE: + result = (givenVal >= storedVal); + break; + + case OP_LE: + result = (givenVal >= storedVal); + break; + + default: + throw new AssertionException("Invalid operation code"); + } + return result; + } + + private boolean matchBooleanValue(Boolean givenVal) + throws ELdapException { + boolean result; + Boolean storedVal; + + if (!(mVal.equalsIgnoreCase("true") || + mVal.equalsIgnoreCase("false"))) + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INVALID_ATTR_VALUE", + mVal)); + storedVal = new Boolean(mVal); + switch (mOp) { + case OP_EQUAL: + result = (givenVal.equals(storedVal)); + break; + + case OP_NEQUAL: + case OP_LT: + case OP_GT: + case OP_GE: + case OP_LE: + result = (!givenVal.equals(storedVal)); + break; + + default: + throw new AssertionException("Invalid operation code"); + } + return result; + } + + public String toString() { + String op = null; + + switch (mOp) { + case ILdapExpression.OP_EQUAL: + op = ILdapExpression.EQUAL_STR; + break; + + case ILdapExpression.OP_NEQUAL: + op = ILdapExpression.NEQUAL_STR; + break; + + case ILdapExpression.OP_GT: + op = ILdapExpression.GT_STR; + break; + + case ILdapExpression.OP_LT: + op = ILdapExpression.LT_STR; + break; + + case ILdapExpression.OP_GE: + op = ILdapExpression.GE_STR; + break; + + case ILdapExpression.OP_LE: + op = ILdapExpression.LE_STR; + break; + } + if (mPfx != null && mPfx.length() > 0) + return mPfx + "." + mVar + " " + op + " " + mVal; + else + return mVar + " " + op + " " + mVal; + } + + private static ExpressionComps parseForEquality(String expression) { + int index = expression.indexOf(ILdapExpression.EQUAL_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_EQUAL; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForInEquality(String expression) { + int index = expression.indexOf(ILdapExpression.NEQUAL_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_NEQUAL; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForGT(String expression) { + int index = expression.indexOf(ILdapExpression.GT_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_GT; + String val = expression.substring(index + 1).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForLT(String expression) { + int index = expression.indexOf(ILdapExpression.LT_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_LT; + String val = expression.substring(index + 1).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForGE(String expression) { + int index = expression.indexOf(ILdapExpression.GE_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_GE; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } + + private static ExpressionComps parseForLE(String expression) { + int index = expression.indexOf(ILdapExpression.LE_STR); + + if (index < 0) + return null; + else { + String attr = expression.substring(0, index).trim(); + int op = OP_LE; + String val = expression.substring(index + 2).trim(); + + return new ExpressionComps(attr, op, val); + } + } +} + + +class ExpressionComps { + String attr; + int op; + String val; + + public ExpressionComps(String a, int o, String v) { + attr = a; + op = o; + val = v; + } + + public String getAttr() { + return attr; + } + + public int getOp() { + return op; + } + + public String getVal() { + return val; + } +} + diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/PublishObject.java b/pki/base/common/src/com/netscape/cmscore/ldap/PublishObject.java new file mode 100644 index 000000000..6818a48bf --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/PublishObject.java @@ -0,0 +1,92 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.security.*; +import java.security.cert.*; +import netscape.security.x509.*; +import netscape.security.util.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.ldap.*; + + +/** + * The object to publish or unpublish: a certificate or a CRL + */ +public class PublishObject { + public static final String CERT = "cert"; + public static final String CERTS = "certs"; + public static final String CRL = "crl"; + private String mObjectType = null; + private X509CertImpl mCert = null; + private X509CertImpl[] mCerts = null; + private X509CRLImpl mCRL = null; + private int mIndex = 0; + + public PublishObject() { + } + + public String getType() { + return mObjectType; + } + + public void setCert(X509CertImpl cert) { + mObjectType = CERT; + mCert = cert; + mCerts = null; + mCRL = null; + } + + public X509CertImpl getCert() { + return mCert; + } + + public void setCerts(X509CertImpl[] certs) { + mObjectType = CERTS; + mCerts = certs; + mCert = null; + mCRL = null; + } + + public X509CertImpl[] getCerts() { + return mCerts; + } + + public void setIndex(int index) { + mIndex = index; + } + + public int getIndex() { + return mIndex; + } + + public void setCRL(X509CRLImpl crl) { + mObjectType = CRL; + mCert = null; + mCerts = null; + mCRL = crl; + } + + public X509CRLImpl getCRL() { + return mCRL; + } + +} diff --git a/pki/base/common/src/com/netscape/cmscore/ldap/PublisherProcessor.java b/pki/base/common/src/com/netscape/cmscore/ldap/PublisherProcessor.java new file mode 100644 index 000000000..488524e9d --- /dev/null +++ b/pki/base/common/src/com/netscape/cmscore/ldap/PublisherProcessor.java @@ -0,0 +1,1506 @@ +// --- BEGIN COPYRIGHT BLOCK --- +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// (C) 2007 Red Hat, Inc. +// All rights reserved. +// --- END COPYRIGHT BLOCK --- +package com.netscape.cmscore.ldap; + + +import java.io.*; +import java.util.*; +import java.net.*; +import java.util.*; +import java.text.*; +import java.math.*; +import java.security.*; +import java.security.cert.X509Certificate; +import javax.servlet.*; +import javax.servlet.http.*; +import java.security.cert.*; +import netscape.ldap.*; +import netscape.security.util.*; +import netscape.security.x509.*; +import com.netscape.certsrv.common.*; +import com.netscape.certsrv.base.*; +import com.netscape.certsrv.logging.*; +import com.netscape.certsrv.authority.*; +import com.netscape.certsrv.ca.*; +import com.netscape.certsrv.dbs.*; +import com.netscape.certsrv.dbs.certdb.*; +import com.netscape.certsrv.request.*; +import com.netscape.certsrv.apps.*; +import com.netscape.certsrv.ldap.*; +import com.netscape.certsrv.publish.*; + +import com.netscape.cmscore.util.*; +import com.netscape.cmscore.cert.*; +import com.netscape.cmscore.dbs.*; +import com.netscape.cmscore.util.Debug; + + +public class PublisherProcessor implements + IPublisherProcessor, IXcertPublisherProcessor { + + public Hashtable mPublisherPlugins = new Hashtable(); + public Hashtable mPublisherInsts = new Hashtable(); + public Hashtable mMapperPlugins = new Hashtable(); + public Hashtable mMapperInsts = new Hashtable(); + public Hashtable mRulePlugins = new Hashtable(); + public Hashtable mRuleInsts = new Hashtable(); + + /** + protected PublishRuleSet mRuleSet = null; + **/ + protected LdapConnModule mLdapConnModule = null; + + private IConfigStore mConfig = null; + private IConfigStore mLdapConfig = null; + private String mId = null; + private ILogger mLogger = CMS.getLogger(); + + protected ICertAuthority mAuthority = null; + protected LdapRequestListener mLdapRequestListener = null; + private boolean mCreateOwnDNEntry = false; + private boolean mInited = false; + + public PublisherProcessor(String id) { + mId = id; + } + + public String getId() { + return mId; + } + + public void setId(String id) { + mId = id; + } + + public IConfigStore getConfigStore() { + return mConfig; + } + + public void init(ISubsystem authority, IConfigStore config) + throws EBaseException { + mConfig = config; + mAuthority = (ICertAuthority) authority; + + // load publisher implementation + IConfigStore publisherConfig = config.getSubStore("publisher"); + IConfigStore c = publisherConfig.getSubStore(PROP_IMPL); + mCreateOwnDNEntry = mConfig.getBoolean("createOwnDNEntry", false); + Enumeration mImpls = c.getSubStoreNames(); + + while (mImpls.hasMoreElements()) { + String id = (String) mImpls.nextElement(); + String pluginPath = c.getString(id + "." + PROP_CLASS); + PublisherPlugin plugin = new PublisherPlugin(id, pluginPath); + + mPublisherPlugins.put(id, plugin); + } + if (Debug.ON) + Debug.trace("loaded publisher plugins"); + + // load publisher instances + c = publisherConfig.getSubStore(PROP_INSTANCE); + Enumeration instances = c.getSubStoreNames(); + + while (instances.hasMoreElements()) { + String insName = (String) instances.nextElement(); + String implName = c.getString(insName + "." + + PROP_PLUGIN); + PublisherPlugin plugin = + (PublisherPlugin) mPublisherPlugins.get(implName); + + if (plugin == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_PLUGIN_NOT_FIND", implName)); + throw new ELdapException(implName); + } + String className = plugin.getClassPath(); + + // Instantiate and init the publisher. + boolean isEnable = false; + ILdapPublisher publisherInst = null; + + try { + publisherInst = (ILdapPublisher) + Class.forName(className).newInstance(); + IConfigStore pConfig = + c.getSubStore(insName); + + publisherInst.init(pConfig); + isEnable = true; + + } catch (ClassNotFoundException e) { + String errMsg = "PublisherProcessor:: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (IllegalAccessException e) { + String errMsg = "PublisherProcessor:: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (InstantiationException e) { + String errMsg = "PublisherProcessor: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (Throwable e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_SKIP_PUBLISHER", insName, e.toString())); + // Let the server continue if it is a + // mis-configuration. But the instance + // will be skipped. This give another + // chance to the user to re-configure + // the server via console. + } + + if (publisherInst == null) { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } + + if (insName == null) { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", insName)); + } + + // add publisher instance to list. + mPublisherInsts.put(insName, new + PublisherProxy(isEnable, publisherInst)); + log(ILogger.LL_INFO, "publisher instance " + insName + " added"); + if (Debug.ON) + Debug.trace("loaded publisher instance " + insName + " impl " + implName); + } + + // load mapper implementation + IConfigStore mapperConfig = config.getSubStore("mapper"); + + c = mapperConfig.getSubStore(PROP_IMPL); + mImpls = c.getSubStoreNames(); + while (mImpls.hasMoreElements()) { + String id = (String) mImpls.nextElement(); + String pluginPath = c.getString(id + "." + PROP_CLASS); + MapperPlugin plugin = new MapperPlugin(id, pluginPath); + + mMapperPlugins.put(id, plugin); + } + if (Debug.ON) + Debug.trace("loaded mapper plugins"); + + // load mapper instances + c = mapperConfig.getSubStore(PROP_INSTANCE); + instances = c.getSubStoreNames(); + while (instances.hasMoreElements()) { + String insName = (String) instances.nextElement(); + String implName = c.getString(insName + "." + + PROP_PLUGIN); + MapperPlugin plugin = + (MapperPlugin) mMapperPlugins.get(implName); + + if (plugin == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_MAPPER_NOT_FIND", implName)); + throw new ELdapException(implName); + } + String className = plugin.getClassPath(); + + if (Debug.ON) + Debug.trace("loaded mapper className=" + className); + + // Instantiate and init the mapper + boolean isEnable = false; + ILdapMapper mapperInst = null; + + try { + mapperInst = (ILdapMapper) + Class.forName(className).newInstance(); + IConfigStore mConfig = + c.getSubStore(insName); + + mapperInst.init(mConfig); + isEnable = true; + } catch (ClassNotFoundException e) { + String errMsg = "PublisherProcessor:: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (IllegalAccessException e) { + String errMsg = "PublisherProcessor:: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (InstantiationException e) { + String errMsg = "PublisherProcessor: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (Throwable e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_SKIP_MAPPER", insName, e.toString())); + // Let the server continue if it is a + // mis-configuration. But the instance + // will be skipped. This give another + // chance to the user to re-configure + // the server via console. + } + + if (mapperInst == null) { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } + + // add manager instance to list. + mMapperInsts.put(insName, new MapperProxy( + isEnable, mapperInst)); + + log(ILogger.LL_INFO, "mapper instance " + insName + " added"); + if (Debug.ON) + Debug.trace("loaded mapper instance " + insName + " impl " + implName); + } + + // load rule implementation + IConfigStore ruleConfig = config.getSubStore("rule"); + + c = ruleConfig.getSubStore(PROP_IMPL); + mImpls = c.getSubStoreNames(); + while (mImpls.hasMoreElements()) { + String id = (String) mImpls.nextElement(); + String pluginPath = c.getString(id + "." + PROP_CLASS); + RulePlugin plugin = new RulePlugin(id, pluginPath); + + mRulePlugins.put(id, plugin); + } + if (Debug.ON) + Debug.trace("loaded rule plugins"); + + // load rule instances + c = ruleConfig.getSubStore(PROP_INSTANCE); + instances = c.getSubStoreNames(); + while (instances.hasMoreElements()) { + String insName = (String) instances.nextElement(); + String implName = c.getString(insName + "." + + PROP_PLUGIN); + RulePlugin plugin = + (RulePlugin) mRulePlugins.get(implName); + + if (plugin == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_RULE_NOT_FIND", implName)); + throw new ELdapException(implName); + } + String className = plugin.getClassPath(); + + if (Debug.ON) + Debug.trace("loaded rule className=" + className); + + // Instantiate and init the rule + IConfigStore mConfig = null; + + try { + ILdapRule ruleInst = null; + + ruleInst = (ILdapRule) + Class.forName(className).newInstance(); + mConfig = c.getSubStore(insName); + ruleInst.init(this, mConfig); + ruleInst.setInstanceName(insName); + + // add manager instance to list. + if (Debug.ON) + Debug.trace("ADDING RULE " + insName + " " + ruleInst); + mRuleInsts.put(insName, ruleInst); + log(ILogger.LL_INFO, "rule instance " + + insName + " added"); + } catch (ClassNotFoundException e) { + String errMsg = "PublisherProcessor:: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (IllegalAccessException e) { + String errMsg = "PublisherProcessor:: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (InstantiationException e) { + String errMsg = "PublisherProcessor: init()-" + e.toString(); + + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_PUBLISHER_INIT_FAILED", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (Throwable e) { + if (mConfig == null) { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } + mConfig.putString(ILdapRule.PROP_ENABLE, + "false"); + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_SKIP_RULE", insName, e.toString())); + // Let the server continue if it is a + // mis-configuration. But the instance + // will be skipped. This give another + // chance to the user to re-configure + // the server via console. + } + if (Debug.ON) + Debug.trace("loaded rule instance " + insName + " impl " + implName); + } + + startup(); + mInited = true; + log(ILogger.LL_INFO, "publishing initialization done"); + } + + /** + * Retrieves LDAP connection module. + * <P> + * + * @return LDAP connection instance + */ + public ILdapConnModule getLdapConnModule() { + return mLdapConnModule; + } + + public void setLdapConnModule(ILdapConnModule m) { + mLdapConnModule = (LdapConnModule)m; + } + + /** + * init ldap connection + */ + private void initLdapConn(IConfigStore ldapConfig) + throws EBaseException { + IConfigStore c = ldapConfig; + + try { + //c = authConfig.getSubStore(PROP_LDAP_PUBLISH_SUBSTORE); + if (c != null && c.size() > 0) { + mLdapConnModule = new LdapConnModule(); + mLdapConnModule.init(this, c); + CMS.debug("LdapPublishing connection inited"); + } else { + log(ILogger.LL_FAILURE, + "No Ldap Module configuration found"); + throw new ELdapException( + CMS.getUserMessage("CMS_LDAP_NO_LDAP_PUBLISH_CONFIG_FOUND")); + } + + } catch (ELdapException e) { + log(ILogger.LL_FAILURE, + "Ldap Publishing Module failed with " + e); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_INIT_LDAP_PUBLISH_MODULE_FAILED", e.toString())); + } + } + + public void startup() throws EBaseException { + CMS.debug("PublisherProcessor: startup()"); + mLdapConfig = mConfig.getSubStore(PROP_LDAP_PUBLISH_SUBSTORE); + if (mLdapConfig.getBoolean(PROP_ENABLE, false)) { + CMS.debug("PublisherProcessor: about to initLdapConn"); + initLdapConn(mLdapConfig); + } else { + CMS.debug("No LdapPublishing enabled"); + } + + if (mConfig.getBoolean(PROP_ENABLE, false)) { + mLdapRequestListener = new LdapRequestListener(); + mLdapRequestListener.init(this, mLdapConfig); + mAuthority.registerRequestListener(mLdapRequestListener); + IConfigStore queueConfig = mConfig.getSubStore(PROP_QUEUE_PUBLISH_SUBSTORE); + if (queueConfig != null) { + boolean isPublishingQueueEnabled = queueConfig.getBoolean("enable", false); + int publishingQueuePriorityLevel = queueConfig.getInteger("priorityLevel", 0); + int maxNumberOfPublishingThreads = queueConfig.getInteger("maxNumberOfThreads", 1); + int publishingQueuePageSize = queueConfig.getInteger("pageSize", 100); + int savePublishingStatus = queueConfig.getInteger("saveStatus", 0); + CMS.debug("PublisherProcessor: startup: Publishing Queue Enabled: " + isPublishingQueueEnabled + + " Priority Level: " + publishingQueuePriorityLevel + + " Maximum Number of Threads: " + maxNumberOfPublishingThreads + + " Page Size: "+ publishingQueuePageSize); + IRequestNotifier reqNotifier = ((ICertificateAuthority)mAuthority).getRequestNotifier(); + reqNotifier.setPublishingQueue (isPublishingQueueEnabled, + publishingQueuePriorityLevel, + maxNumberOfPublishingThreads, + publishingQueuePageSize, + savePublishingStatus); + } + } + } + + public void shutdown() { + CMS.debug("Shuting down publishing."); + try { + if (mLdapConnModule != null) { + mLdapConnModule.getLdapConnFactory().reset(); + } + if (mLdapRequestListener != null) { + //mLdapRequestListener.shutdown(); + mAuthority.removeRequestListener(mLdapRequestListener); + } + } catch (Exception e) { + // ignore + } + } + + public Hashtable getRulePlugins() { + return mRulePlugins; + } + + public Hashtable getRuleInsts() { + return mRuleInsts; + } + + public Hashtable getMapperPlugins() { + return mMapperPlugins; + } + + public Hashtable getPublisherPlugins() { + return mPublisherPlugins; + } + + public Hashtable getMapperInsts() { + return mMapperInsts; + } + + public Hashtable getPublisherInsts() { + return mPublisherInsts; + } + + //certType can be client,server,ca,crl,smime + //XXXshould make it static to make it faster + public Enumeration getRules(String publishingType) { + Vector rules = new Vector(); + Enumeration e = mRuleInsts.keys(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + + if (name == null) { + if (Debug.ON) + Debug.trace("rule name is " + "null"); + return null; + } else { + if (Debug.ON) + Debug.trace("rule name is " + name); + } + + //this is the only rule we support now + LdapRule rule = (LdapRule) (mRuleInsts.get(name)); + + if (rule.enabled() && rule.getType().equals(publishingType)) { + // check if the predicate match + ILdapExpression exp = rule.getPredicate(); + + try { + SessionContext sc = SessionContext.getContext(); + + if (exp != null && !exp.evaluate(sc)) + continue; + } catch (Exception ex) { + // do nothing + } + rules.addElement(rule); + if (Debug.ON) + Debug.trace("added rule " + name + " for " + publishingType); + } + } + return rules.elements(); + } + + public Enumeration getRules(String publishingType, IRequest req) { + if (req == null) { + return getRules(publishingType); + } + + Vector rules = new Vector(); + Enumeration e = mRuleInsts.keys(); + + while (e.hasMoreElements()) { + String name = (String) e.nextElement(); + + if (name == null) { + if (Debug.ON) + Debug.trace("rule name is " + "null"); + return null; + } else { + if (Debug.ON) + Debug.trace("rule name is " + name); + } + + //this is the only rule we support now + LdapRule rule = (LdapRule) (mRuleInsts.get(name)); + + if (rule.enabled() && rule.getType().equals(publishingType)) { + // check if the predicate match + ILdapExpression exp = rule.getPredicate(); + + try { + if (exp != null && !exp.evaluate(req)) + continue; + } catch (Exception ex) { + ex.printStackTrace(); + } + + rules.addElement(rule); + if (Debug.ON) + Debug.trace("added rule " + name + " for " + publishingType + + " request: " + req.getRequestId()); + } + } + return rules.elements(); + } + + /** + public PublishRuleSet getPublishRuleSet() + { + return mRuleSet; + } + **/ + + public Vector getMapperDefaultParams(String implName) throws + ELdapException { + // is this a registered implname? + MapperPlugin plugin = (MapperPlugin) + mMapperPlugins.get(implName); + + if (plugin == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_MAPPER_NOT_FIND", implName)); + throw new ELdapException(implName); + } + + // XXX can find an instance of this plugin in existing + // mapper instances to avoid instantiation just for this. + + // a temporary instance + ILdapMapper mapperInst = null; + String className = plugin.getClassPath(); + + try { + mapperInst = (ILdapMapper) + Class.forName(className).newInstance(); + Vector v = mapperInst.getDefaultParams(); + + return v; + } catch (InstantiationException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_MAPPER", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (ClassNotFoundException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_MAPPER", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (IllegalAccessException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_MAPPER", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } + } + + public Vector getMapperInstanceParams(String insName) throws + ELdapException { + ILdapMapper mapperInst = null; + MapperProxy proxy = (MapperProxy) mMapperInsts.get(insName); + + if (proxy == null) { + return null; + } + mapperInst = proxy.getMapper(); + if (mapperInst == null) { + return null; + } + Vector v = mapperInst.getInstanceParams(); + + return v; + } + + public Vector getPublisherDefaultParams(String implName) throws + ELdapException { + // is this a registered implname? + PublisherPlugin plugin = (PublisherPlugin) + mPublisherPlugins.get(implName); + + if (plugin == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_PLUGIN_NOT_FIND", implName)); + throw new ELdapException(implName); + } + + // XXX can find an instance of this plugin in existing + // publisher instantces to avoid instantiation just for this. + + // a temporary instance + ILdapPublisher publisherInst = null; + String className = plugin.getClassPath(); + + try { + publisherInst = (ILdapPublisher) + Class.forName(className).newInstance(); + Vector v = publisherInst.getDefaultParams(); + + return v; + } catch (InstantiationException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_PUBLISHER", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (ClassNotFoundException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_PUBLISHER", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (IllegalAccessException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_PUBLISHER", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } + } + + public boolean isMapperInstanceEnable(String insName) { + MapperProxy proxy = (MapperProxy) + mMapperInsts.get(insName); + + if (proxy == null) { + return false; + } + return proxy.isEnable(); + } + + public ILdapMapper getActiveMapperInstance(String insName) { + MapperProxy proxy = (MapperProxy) mMapperInsts.get(insName); + + if (proxy == null) + return null; + if (proxy.isEnable()) + return proxy.getMapper(); + else + return null; + } + + public ILdapMapper getMapperInstance(String insName) { + MapperProxy proxy = (MapperProxy) mMapperInsts.get(insName); + + if (proxy == null) + return null; + return proxy.getMapper(); + } + + public boolean isPublisherInstanceEnable(String insName) { + PublisherProxy proxy = (PublisherProxy) + mPublisherInsts.get(insName); + + if (proxy == null) { + return false; + } + return proxy.isEnable(); + } + + public ILdapPublisher getActivePublisherInstance(String insName) { + PublisherProxy proxy = (PublisherProxy) + mPublisherInsts.get(insName); + + if (proxy == null) { + return null; + } + if (proxy.isEnable()) + return proxy.getPublisher(); + else + return null; + } + + public ILdapPublisher getPublisherInstance(String insName) { + PublisherProxy proxy = (PublisherProxy) + mPublisherInsts.get(insName); + + if (proxy == null) { + return null; + } + return proxy.getPublisher(); + } + + public Vector getPublisherInstanceParams(String insName) throws + ELdapException { + ILdapPublisher publisherInst = getPublisherInstance(insName); + + if (publisherInst == null) { + return null; + } + Vector v = publisherInst.getInstanceParams(); + + return v; + } + + public Vector getRuleDefaultParams(String implName) throws + ELdapException { + // is this a registered implname? + RulePlugin plugin = (RulePlugin) + mRulePlugins.get(implName); + + if (plugin == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_RULE_NOT_FIND", implName)); + throw new ELdapException(implName); + } + + // XXX can find an instance of this plugin in existing + // rule instantces to avoid instantiation just for this. + + // a temporary instance + ILdapRule ruleInst = null; + String className = plugin.getClassPath(); + + try { + ruleInst = (ILdapRule) + Class.forName(className).newInstance(); + + Vector v = ruleInst.getDefaultParams(); + + return v; + } catch (InstantiationException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (ClassNotFoundException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (IllegalAccessException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } + } + + public Vector getRuleInstanceParams(String implName) throws + ELdapException { + // is this a registered implname? + RulePlugin plugin = (RulePlugin) + mRulePlugins.get(implName); + + if (plugin == null) { + log(ILogger.LL_FAILURE, + CMS.getLogMessage("CMSCORE_LDAP_RULE_NOT_FIND", implName)); + throw new ELdapException(implName); + } + + // XXX can find an instance of this plugin in existing + // rule instantces to avoid instantiation just for this. + + // a temporary instance + ILdapRule ruleInst = null; + String className = plugin.getClassPath(); + + try { + ruleInst = (ILdapRule) + Class.forName(className).newInstance(); + Vector v = ruleInst.getInstanceParams(); + IConfigStore rc = ruleInst.getConfigStore(); + + return v; + } catch (InstantiationException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (ClassNotFoundException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } catch (IllegalAccessException e) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_NEW_RULE", e.toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_FAIL_LOAD_CLASS", className)); + } + } + + /** + * set published flag - true when published, false when unpublished. + * not exist means not published. + */ + public void setPublishedFlag(BigInteger serialNo, boolean published) { + if (!(mAuthority instanceof ICertificateAuthority)) + return; + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + + try { + ICertificateRepository certdb = (ICertificateRepository) ca.getCertificateRepository(); + ICertRecord certRec = (ICertRecord) certdb.readCertificateRecord(serialNo); + MetaInfo metaInfo = certRec.getMetaInfo(); + + if (metaInfo == null) { + metaInfo = new MetaInfo(); + } + metaInfo.set( + CertRecord.META_LDAPPUBLISH, String.valueOf(published)); + ModificationSet modSet = new ModificationSet(); + + modSet.add(ICertRecord.ATTR_META_INFO, + Modification.MOD_REPLACE, metaInfo); + certdb.modifyCertificateRecord(serialNo, modSet); + } catch (EBaseException e) { + // not fatal. just log warning. + log(ILogger.LL_WARN, + "Cannot mark cert 0x" + serialNo.toString(16) + " published as " + published + + " in the ldap directory. Cert Record not found. Error: " + + e.toString() + + " Don't be alarmed if it's a subordinate ca or clone's ca siging cert. Otherwise your internal db may be corrupted."); + } + } + + /** + * Publish ca cert, UpdateDir.java, jobs, request listeners + */ + public void publishCACert(X509Certificate cert) + throws ELdapException { + boolean error = false; + String errorRule = ""; + + if (!enabled()) + return; + + CMS.debug("PublishProcessor::publishCACert"); + + // get mapper and publisher for cert type. + Enumeration rules = getRules(PROP_LOCAL_CA); + + if (rules == null || !rules.hasMoreElements()) { + if (isClone()) { + log(ILogger.LL_WARN, "No rule is found for publishing: " + PROP_LOCAL_CA + " in this clone."); + return; + } else { + Debug.trace(CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOUND", PROP_LOCAL_CA)); + //log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOUND", PROP_LOCAL_CA)); + //throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", PROP_LOCAL_CA)); + return; + } + } + while (rules.hasMoreElements()) { + LdapRule rule = (LdapRule) rules.nextElement(); + + if( rule == null ) { + CMS.debug( "PublisherProcessor::publishCACert() - " + + "rule is null!" ); + throw new ELdapException( "rule is null" ); + } + + log(ILogger.LL_INFO, "publish certificate type=" + PROP_LOCAL_CA + + " rule=" + rule.getInstanceName() + " publisher=" + + rule.getPublisher()); + + try { + ILdapMapper mapper = null; + + String mapperName = rule.getMapper(); + + if (mapperName != null && + !mapperName.trim().equals("")) { + mapper = getActiveMapperInstance(mapperName); + } + + publishNow(mapper, getActivePublisherInstance(rule.getPublisher()), null/* NO REQUEsT */, cert); + log(ILogger.LL_INFO, "published certificate using rule=" + + rule.getInstanceName()); + } catch (Exception e) { + // continue publishing even publisher has errors + //log(ILogger.LL_WARN, e.toString()); + CMS.debug("PublisherProcessor::publishCACert returned error: " + e.toString()); + error = true; + errorRule = errorRule + " " + rule.getInstanceName() + + " error:" + e.toString(); + } + } + // set the ldap published flag. + if (!error) { + setPublishedFlag(cert.getSerialNumber(), true); + } else { + throw new + ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule)); + } + } + + /** + * This function is never called. CMS does not unpublish + * CA certificate. + */ + public void unpublishCACert(X509Certificate cert) + throws ELdapException { + boolean error = false; + String errorRule = ""; + + if (!enabled()) + return; + + // get mapper and publisher for cert type. + Enumeration rules = getRules(PROP_LOCAL_CA); + + if (rules == null || !rules.hasMoreElements()) { + if (isClone()) { + log(ILogger.LL_WARN, "No rule is found for unpublishing: " + PROP_LOCAL_CA + " in this clone."); + return; + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_UNPUBLISHING_RULE_FOUND", PROP_LOCAL_CA)); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", PROP_LOCAL_CA)); + } + } + + while (rules.hasMoreElements()) { + LdapRule rule = (LdapRule) rules.nextElement(); + + if( rule == null ) { + CMS.debug( "PublisherProcessor::unpublishCACert() - " + + "rule is null!" ); + throw new ELdapException( "rule is null" ); + } + + try { + log(ILogger.LL_INFO, "unpublish certificate type=" + + PROP_LOCAL_CA + " rule=" + rule.getInstanceName() + + " publisher=" + rule.getPublisher()); + + ILdapMapper mapper = null; + + String mapperName = rule.getMapper(); + + if (mapperName != null && + !mapperName.trim().equals("")) { + mapper = getActiveMapperInstance(mapperName); + } + + unpublishNow(mapper, getActivePublisherInstance(rule.getPublisher()), null/* NO REQUEST */, cert); + log(ILogger.LL_INFO, "unpublished certificate using rule=" + + rule.getInstanceName()); + } catch (Exception e) { + // continue publishing even publisher has errors + //log(ILogger.LL_WARN, e.toString()); + error = true; + errorRule = errorRule + " " + rule.getInstanceName(); + } + } + + // set the ldap published flag. + if (!error) { + setPublishedFlag(cert.getSerialNumber(), false); + } else { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_FAILED", errorRule)); + } + } + + /** + * Publish crossCertificatePair + */ + public void publishXCertPair(byte[] pair) + throws ELdapException { + boolean error = false; + String errorRule = ""; + + if (!enabled()) + return; + CMS.debug("PublisherProcessor: in publishXCertPair()"); + + // get mapper and publisher for cert type. + Enumeration rules = getRules(PROP_XCERT); + + if (rules == null || !rules.hasMoreElements()) { + if (isClone()) { + log(ILogger.LL_WARN, "No rule is found for publishing: " + PROP_LOCAL_CA + " in this clone."); + return; + } else { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOUND", PROP_XCERT)); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", PROP_XCERT)); + } + } + while (rules.hasMoreElements()) { + LdapRule rule = (LdapRule) rules.nextElement(); + + if( rule == null ) { + CMS.debug( "PublisherProcessor::publishXCertPair() - " + + "rule is null!" ); + throw new ELdapException( "rule is null" ); + } + + log(ILogger.LL_INFO, "publish certificate type=" + PROP_XCERT + + " rule=" + rule.getInstanceName() + " publisher=" + + rule.getPublisher()); + try { + ILdapMapper mapper = null; + + String mapperName = rule.getMapper(); + + if (mapperName != null && + !mapperName.trim().equals("")) { + mapper = getActiveMapperInstance(mapperName); + } + + publishNow(mapper, getActivePublisherInstance(rule.getPublisher()), null/* NO REQUEsT */, pair); + log(ILogger.LL_INFO, "published Xcertificates using rule=" + + rule.getInstanceName()); + } catch (Exception e) { + // continue publishing even publisher has errors + //log(ILogger.LL_WARN, e.toString()); + error = true; + errorRule = errorRule + " " + rule.getInstanceName() + + " error:" + e.toString(); + + CMS.debug("PublisherProcessor::publishXCertPair: error: " + e.toString()); + } + } + } + + /** + * Publishs regular user certificate based on the criteria + * set in the request. + */ + public void publishCert(X509Certificate cert, IRequest req) + throws ELdapException { + boolean error = false; + String errorRule = ""; + + CMS.debug("In PublisherProcessor::publishCert"); + if (!enabled()) + return; + + // get mapper and publisher for cert type. + Enumeration rules = getRules("certs", req); + + // Bugscape #52306 - Remove superfluous log messages on failure + if (rules == null || !rules.hasMoreElements()) { + CMS.debug("Publishing: can't find publishing rule,exiting routine."); + + error = true; + errorRule = "No rules enabled"; + } + + while (rules != null && rules.hasMoreElements()) { + LdapRule rule = (LdapRule) rules.nextElement(); + + try { + log(ILogger.LL_INFO, + "publish certificate (with request) type=" + + "certs" + " rule=" + rule.getInstanceName() + + " publisher=" + rule.getPublisher()); + ILdapPublisher p = getActivePublisherInstance(rule.getPublisher()); + ILdapMapper m = null; + String mapperName = rule.getMapper(); + + if (mapperName != null) { + m = getActiveMapperInstance(mapperName); + } + publishNow(m, p, req, cert); + log(ILogger.LL_INFO, "published certificate using rule=" + + rule.getInstanceName()); + } catch (Exception e) { + // continue publishing even publisher has errors + //log(ILogger.LL_WARN, e.toString()); + error = true; + errorRule = errorRule + " " + rule.getInstanceName(); + } + } + // set the ldap published flag. + if (!error) { + setPublishedFlag(cert.getSerialNumber(), true); + } else { + CMS.debug("PublishProcessor::publishCert : " + CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED",errorRule)); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule)); + } + } + + /** + * Unpublish user certificate. This is used by + * UnpublishExpiredJob. + */ + public void unpublishCert(X509Certificate cert, IRequest req) + throws ELdapException { + boolean error = false; + String errorRule = ""; + + if (!enabled()) + return; + + // get mapper and publisher for cert type. + Enumeration rules = getRules("certs", req); + + if (rules == null || !rules.hasMoreElements()) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_UNPUBLISHING_RULE_FOUND_FOR_REQUEST", "certs", req.getRequestId().toString())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", + req.getRequestId().toString())); + } + + while (rules.hasMoreElements()) { + LdapRule rule = (LdapRule) rules.nextElement(); + + if( rule == null ) { + CMS.debug( "PublisherProcessor::unpublishCert() - " + + "rule is null!" ); + throw new ELdapException( "rule is null" ); + } + + try { + log(ILogger.LL_INFO, + "unpublish certificate (with request) type=" + + "certs" + " rule=" + rule.getInstanceName() + + " publisher=" + rule.getPublisher()); + + ILdapMapper mapper = null; + + String mapperName = rule.getMapper(); + + if (mapperName != null && + !mapperName.trim().equals("")) { + mapper = getActiveMapperInstance(mapperName); + } + + unpublishNow(mapper, getActivePublisherInstance(rule.getPublisher()), + req, cert); + log(ILogger.LL_INFO, "unpublished certificate using rule=" + + rule.getInstanceName()); + } catch (Exception e) { + // continue publishing even publisher has errors + //log(ILogger.LL_WARN, e.toString()); + error = true; + errorRule = errorRule + " " + rule.getInstanceName(); + } + } + + // set the ldap published flag. + if (!error) { + setPublishedFlag(cert.getSerialNumber(), false); + } else { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_UNPUBLISH_FAILED", errorRule)); + } + } + + /** + * publishes a crl by mapping the issuer name in the crl to an entry + * and publishing it there. entry must be a certificate authority. + * Note that this is used by cmsgateway/cert/UpdateDir.java + */ + public void publishCRL(X509CRLImpl crl, String crlIssuingPointId) + throws ELdapException { + boolean error = false; + String errorRule = ""; + + + if (!enabled()) + return; + ILdapMapper mapper = null; + ILdapPublisher publisher = null; + + // get mapper and publisher for cert type. + Enumeration rules = getRules(PROP_LOCAL_CRL); + + if (rules == null || !rules.hasMoreElements()) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOR_CRL")); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", + PROP_LOCAL_CRL)); + } + + LDAPConnection conn = null; + String dn = null; + + try { + if (mLdapConnModule != null) { + conn = mLdapConnModule.getConn(); + } + while (rules.hasMoreElements()) { + mapper = null; + dn = null; + String result = null; + LdapRule rule = (LdapRule) rules.nextElement(); + + log(ILogger.LL_INFO, "publish crl rule=" + + rule.getInstanceName() + " publisher=" + + rule.getPublisher()); + try { + String mapperName = rule.getMapper(); + + if (mapperName != null && + !mapperName.trim().equals("")) { + mapper = getActiveMapperInstance(mapperName); + } + if (mapper == null || mapper.getImplName().equals("NoMap")) { + dn = ((X500Name) crl.getIssuerDN()).toLdapDNString(); + }else { + + result = ((ILdapMapper) mapper).map(conn, crl); + dn = result; + if (!mCreateOwnDNEntry) { + if (dn == null) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_MAPPER_NOT_MAP", rule.getMapper())); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", + crl.getIssuerDN().toString())); + + } + } + } + publisher = getActivePublisherInstance(rule.getPublisher()); + if (publisher != null) { + if(publisher instanceof com.netscape.cms.publish.publishers.FileBasedPublisher) + ((com.netscape.cms.publish.publishers.FileBasedPublisher)publisher).setIssuingPointId(crlIssuingPointId); + publisher.publish(conn, dn, crl); + log(ILogger.LL_INFO, "published crl using rule=" + rule.getInstanceName()); + } + // continue publishing even publisher has errors + }catch (Exception e) { + //e.printStackTrace(); + CMS.debug( + "Error publishing CRL to " + dn + ": " + e); + error = true; + errorRule = errorRule + " " + rule.getInstanceName(); + + CMS.debug("PublisherProcessor::publishCRL: error: " + e.toString()); + } + } + }catch (ELdapException e) { + //e.printStackTrace(); + CMS.debug( + "Error publishing CRL to " + dn + ": " + e); + throw e; + } finally { + if (conn != null) { + mLdapConnModule.returnConn(conn); + } + } + if (error) + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule)); + } + + /** + * publishes a crl by mapping the issuer name in the crl to an entry + * and publishing it there. entry must be a certificate authority. + */ + public void publishCRL(String dn, X509CRL crl) + throws ELdapException { + boolean error = false; + String errorRule = ""; + + if (!enabled()) + return; + // get mapper and publisher for cert type. + Enumeration rules = getRules(PROP_LOCAL_CRL); + + if (rules == null || !rules.hasMoreElements()) { + log(ILogger.LL_FAILURE, CMS.getLogMessage("CMSCORE_LDAP_NO_RULE_FOR_CRL")); + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_RULE_MATCHED", + PROP_LOCAL_CRL)); + } + + LDAPConnection conn = null; + ILdapPublisher publisher = null; + + try { + if (mLdapConnModule != null) { + conn = mLdapConnModule.getConn(); + } + while (rules.hasMoreElements()) { + LdapRule rule = (LdapRule) rules.nextElement(); + + log(ILogger.LL_INFO, "publish crl dn=" + dn + " rule=" + + rule.getInstanceName() + " publisher=" + + rule.getPublisher()); + try { + publisher = getActivePublisherInstance(rule.getPublisher()); + if (publisher != null) { + publisher.publish(conn, dn, crl); + log(ILogger.LL_INFO, "published crl using rule=" + rule.getInstanceName()); + } + }catch (Exception e) { + CMS.debug( + "Error publishing CRL to " + dn + ": " + e.toString()); + error = true; + errorRule = errorRule + " " + rule.getInstanceName(); + CMS.debug("PublisherProcessor::publishCRL: error: " + e.toString()); + } + } + } catch (ELdapException e) { + CMS.debug( + "Error publishing CRL to " + dn + ": " + e.toString()); + throw e; + } finally { + if (conn != null) { + mLdapConnModule.returnConn(conn); + } + } + if (error) + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_PUBLISH_FAILED", errorRule)); + } + + private void publishNow(ILdapMapper mapper, ILdapPublisher publisher, + IRequest r, Object obj) throws ELdapException { + if (!enabled()) + return; + CMS.debug("PublisherProcessor: in publishNow()"); + LDAPConnection conn = null; + + try { + Object dirdn = null; + + if (mapper != null) { + LdapCertMapResult result = null; + + if (mLdapConnModule != null) { + try { + conn = mLdapConnModule.getConn(); + } catch(ELdapException e) { + throw e; + } + } + try { + if ((mapper instanceof com.netscape.cms.publish.mappers.LdapCertSubjMap) && + ((com.netscape.cms.publish.mappers.LdapCertSubjMap)mapper).useAllEntries()) { + dirdn = ((com.netscape.cms.publish.mappers.LdapCertSubjMap)mapper).mapAll(conn, r, obj); + } else { + dirdn = mapper.map(conn, r, obj); + } + } catch (Throwable e1) { + CMS.debug("Error mapping: mapper=" + mapper + " error=" + e1.toString()); + throw e1; + } + } + + X509Certificate cert = (X509Certificate) obj; + + try { + if (dirdn instanceof Vector) { + int n = ((Vector)dirdn).size(); + for (int i = 0; i < n; i++) { + publisher.publish(conn, (String)(((Vector)dirdn).elementAt(i)), cert); + } + } else if (dirdn instanceof String || + publisher instanceof com.netscape.cms.publish.publishers.FileBasedPublisher) { + publisher.publish(conn, (String)dirdn, cert); + } + } catch (Throwable e1) { + CMS.debug("PublisherProcessor::publishNow : publisher=" + publisher + " error=" + e1.toString()); + throw e1; + } + log(ILogger.LL_INFO, "published certificate serial number: 0x" + + cert.getSerialNumber().toString(16)); + } catch (ELdapException e) { + throw e; + } catch (Throwable e) { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", e.toString())); + } finally { + if (conn != null) { + mLdapConnModule.returnConn(conn); + } + } + } + + // for crosscerts + private void publishNow(ILdapMapper mapper, ILdapPublisher publisher, + IRequest r, byte[] bytes) throws ELdapException { + if (!enabled()) + return; + CMS.debug("PublisherProcessor: in publishNow() for xcerts"); + + // use ca cert publishing map and rule + ICertificateAuthority ca = (ICertificateAuthority) mAuthority; + X509Certificate caCert = (X509Certificate) ca.getCACert(); + + LDAPConnection conn = null; + + try { + String dirdn = null; + + if (mapper != null) { + LdapCertMapResult result = null; + + if (mLdapConnModule != null) { + conn = mLdapConnModule.getConn(); + } + try { + dirdn = mapper.map(conn, r, (Object) caCert); + CMS.debug("PublisherProcessor: dirdn="+dirdn); + + } catch (Throwable e1) { + CMS.debug("Error mapping: mapper=" + mapper + " error=" + e1.toString()); + throw e1; + } + } + + try { + CMS.debug("PublisherProcessor: publisher impl name="+publisher.getImplName()); + + publisher.publish(conn, dirdn, bytes); + } catch (Throwable e1) { + CMS.debug("Error publishing: publisher=" + publisher + " error=" + e1.toString()); + throw e1; + } + log(ILogger.LL_INFO, "published crossCertPair"); + } catch (ELdapException e) { + throw e; + } catch (Throwable e) { + throw new ELdapException(CMS.getUserMessage("CMS_LDAP_NO_MATCH", e.toString())); + } finally { + if (conn != null) { + mLdapConnModule.returnConn(conn); + } + } + } + + private void unpublishNow(ILdapMapper mapper, ILdapPublisher publisher, + IRequest r, Object obj) throws ELdapException { + if (!enabled()) + return; + LDAPConnection conn = null; + + try { + String dirdn = null; + + if (mapper != null) { + LdapCertMapResult result = null; + + if (mLdapConnModule != null) { + conn = mLdapConnModule.getConn(); + } + dirdn = mapper.map(conn, r, obj); + } + X509Certificate cert = (X509Certificate) obj; + + publisher.unpublish(conn, dirdn, cert); + log(ILogger.LL_INFO, "unpublished certificate serial number: 0x" + + cert.getSerialNumber().toString(16)); + } catch (ELdapException e) { + throw e; + } finally { + if (conn != null) { + mLdapConnModule.returnConn(conn); + } + } + } + + public boolean ldapEnabled() { + try { + if (mInited) + return mLdapConfig.getBoolean(PROP_ENABLE, false); + else + return false; + } catch (EBaseException e) { + return false; + } + } + + public boolean enabled() { + try { + if (mInited) + return mConfig.getBoolean(PROP_ENABLE, false); + else + return false; + } catch (EBaseException e) { + return false; + } + } + + public ISubsystem getAuthority() { + return mAuthority; + } + + public boolean isClone() { + if ((mAuthority instanceof ICertificateAuthority) && + ((ICertificateAuthority) mAuthority).isClone()) + return true; + else + return false; + } + + /** + * logs an entry in the log file. + */ + public void log(int level, String msg) { + if (mLogger == null) + return; + mLogger.log(ILogger.EV_SYSTEM, + ILogger.S_LDAP, level, "Publishing: " + msg); + } +} |