0001: package org.bouncycastle.x509.util;
0002:
0003: import org.bouncycastle.asn1.ASN1InputStream;
0004: import org.bouncycastle.asn1.x509.CertificatePair;
0005: import org.bouncycastle.asn1.x509.X509CertificateStructure;
0006: import org.bouncycastle.jce.X509LDAPCertStoreParameters;
0007: import org.bouncycastle.jce.provider.X509AttrCertParser;
0008: import org.bouncycastle.jce.provider.X509CRLParser;
0009: import org.bouncycastle.jce.provider.X509CertPairParser;
0010: import org.bouncycastle.jce.provider.X509CertParser;
0011: import org.bouncycastle.util.StoreException;
0012: import org.bouncycastle.util.StreamParsingException;
0013: import org.bouncycastle.x509.X509AttributeCertStoreSelector;
0014: import org.bouncycastle.x509.X509AttributeCertificate;
0015: import org.bouncycastle.x509.X509CRLStoreSelector;
0016: import org.bouncycastle.x509.X509CertPairStoreSelector;
0017: import org.bouncycastle.x509.X509CertStoreSelector;
0018: import org.bouncycastle.x509.X509CertificatePair;
0019:
0020: import javax.naming.Context;
0021: import javax.naming.NamingEnumeration;
0022: import javax.naming.NamingException;
0023: import javax.naming.directory.Attribute;
0024: import javax.naming.directory.DirContext;
0025: import javax.naming.directory.InitialDirContext;
0026: import javax.naming.directory.SearchControls;
0027: import javax.naming.directory.SearchResult;
0028: import javax.security.auth.x500.X500Principal;
0029: import java.io.ByteArrayInputStream;
0030: import java.io.IOException;
0031: import java.security.Principal;
0032: import java.security.cert.CertificateParsingException;
0033: import java.security.cert.X509CRL;
0034: import java.security.cert.X509Certificate;
0035: import java.sql.Date;
0036: import java.util.ArrayList;
0037: import java.util.Collection;
0038: import java.util.HashMap;
0039: import java.util.HashSet;
0040: import java.util.Iterator;
0041: import java.util.List;
0042: import java.util.Map;
0043: import java.util.Properties;
0044: import java.util.Set;
0045:
0046: /**
0047: * This is a general purpose implementation to get X.509 certificates, CRLs,
0048: * attribute certificates and cross certificates from a LDAP location.
0049: * <p/>
0050: * At first a search is performed in the ldap*AttributeNames of the
0051: * {@link org.bouncycastle.jce.X509LDAPCertStoreParameters} with the given
0052: * information of the subject (for all kind of certificates) or issuer (for
0053: * CRLs), respectively, if a {@link org.bouncycastle.x509.X509CertStoreSelector} or
0054: * {@link org.bouncycastle.x509.X509AttributeCertificate} is given with that
0055: * details.
0056: * <p/>
0057: * For the used schemes see:
0058: * <ul>
0059: * <li><a href="http://www.ietf.org/rfc/rfc2587.txt">RFC 2587</a>
0060: * <li><a
0061: * href="http://www3.ietf.org/proceedings/01mar/I-D/pkix-ldap-schema-01.txt">Internet
0062: * X.509 Public Key Infrastructure Additional LDAP Schema for PKIs and PMIs</a>
0063: * </ul>
0064: */
0065: public class LDAPStoreHelper {
0066:
0067: // TODO: cache results
0068:
0069: private X509LDAPCertStoreParameters params;
0070:
0071: public LDAPStoreHelper(X509LDAPCertStoreParameters params) {
0072: this .params = params;
0073: }
0074:
0075: /**
0076: * Initial Context Factory.
0077: */
0078: private static String LDAP_PROVIDER = "com.sun.jndi.ldap.LdapCtxFactory";
0079:
0080: /**
0081: * Processing referrals..
0082: */
0083: private static String REFERRALS_IGNORE = "ignore";
0084:
0085: /**
0086: * Security level to be used for LDAP connections.
0087: */
0088: private static final String SEARCH_SECURITY_LEVEL = "none";
0089:
0090: /**
0091: * Package Prefix for loading URL context factories.
0092: */
0093: private static final String URL_CONTEXT_PREFIX = "com.sun.jndi.url";
0094:
0095: private DirContext connectLDAP() throws NamingException {
0096: Properties props = new Properties();
0097: props.setProperty(Context.INITIAL_CONTEXT_FACTORY,
0098: LDAP_PROVIDER);
0099: props.setProperty(Context.BATCHSIZE, "0");
0100:
0101: props.setProperty(Context.PROVIDER_URL, params.getLdapURL());
0102: props.setProperty(Context.URL_PKG_PREFIXES, URL_CONTEXT_PREFIX);
0103: props.setProperty(Context.REFERRAL, REFERRALS_IGNORE);
0104: props.setProperty(Context.SECURITY_AUTHENTICATION,
0105: SEARCH_SECURITY_LEVEL);
0106:
0107: DirContext ctx = new InitialDirContext(props);
0108: return ctx;
0109: }
0110:
0111: private String parseDN(String subject, String dNAttributeName) {
0112: String temp = subject;
0113: int begin = temp.toLowerCase().indexOf(
0114: dNAttributeName.toLowerCase() + "=");
0115: if (begin == -1) {
0116: return "";
0117: }
0118: temp = temp.substring(begin + dNAttributeName.length());
0119: int end = temp.indexOf(',');
0120: if (end == -1) {
0121: end = temp.length();
0122: }
0123: while (temp.charAt(end - 1) == '\\') {
0124: end = temp.indexOf(',', end + 1);
0125: if (end == -1) {
0126: end = temp.length();
0127: }
0128: }
0129: temp = temp.substring(0, end);
0130: begin = temp.indexOf('=');
0131: temp = temp.substring(begin + 1);
0132: if (temp.charAt(0) == ' ') {
0133: temp = temp.substring(1);
0134: }
0135: if (temp.startsWith("\"")) {
0136: temp = temp.substring(1);
0137: }
0138: if (temp.endsWith("\"")) {
0139: temp = temp.substring(0, temp.length() - 1);
0140: }
0141: return temp;
0142: }
0143:
0144: private Set createCerts(List list, X509CertStoreSelector xselector)
0145: throws StoreException {
0146: Set certSet = new HashSet();
0147:
0148: Iterator it = list.iterator();
0149: X509CertParser parser = new X509CertParser();
0150: while (it.hasNext()) {
0151: try {
0152: parser.engineInit(new ByteArrayInputStream((byte[]) it
0153: .next()));
0154: X509Certificate cert = (X509Certificate) parser
0155: .engineRead();
0156: if (xselector.match((Object) cert)) {
0157: certSet.add(cert);
0158: }
0159:
0160: } catch (Exception e) {
0161:
0162: }
0163: }
0164:
0165: return certSet;
0166: }
0167:
0168: /**
0169: * Can use the subject and serial and the subject and serialNumber of the
0170: * certificate of the given of the X509CertStoreSelector. If a certificate
0171: * for checking is given this has higher precedence.
0172: *
0173: * @param xselector The selector with the search criteria.
0174: * @param attrs Attributes which contain the certificates in the LDAP
0175: * directory.
0176: * @param attrNames Attribute names in teh LDAP directory which correspond to the
0177: * subjectAttributeNames.
0178: * @param subjectAttributeNames Subject attribute names (like "CN", "O", "OU") to use to
0179: * search in the LDAP directory
0180: * @return A list of found DER encoded certificates.
0181: * @throws StoreException if an error occurs while searching.
0182: */
0183: private List certSubjectSerialSearch(
0184: X509CertStoreSelector xselector, String[] attrs,
0185: String attrNames[], String subjectAttributeNames[])
0186: throws StoreException {
0187: // TODO: support also subjectAltNames?
0188: List list = new ArrayList();
0189:
0190: String subject = null;
0191: String serial = null;
0192:
0193: subject = getSubjectAsString(xselector);
0194:
0195: if (xselector.getSerialNumber() != null) {
0196: serial = xselector.getSerialNumber().toString();
0197: }
0198: if (xselector.getCertificate() != null) {
0199: subject = xselector.getCertificate()
0200: .getSubjectX500Principal().getName("RFC1779");
0201: serial = xselector.getCertificate().getSerialNumber()
0202: .toString();
0203: }
0204:
0205: String attrValue = null;
0206: if (subject != null) {
0207: for (int i = 0; i < subjectAttributeNames.length; i++) {
0208: attrValue = parseDN(subject, subjectAttributeNames[i]);
0209: list.addAll(search(attrNames, "*" + attrValue + "*",
0210: attrs));
0211: }
0212: }
0213: if (serial != null
0214: && params.getSearchForSerialNumberIn() != null) {
0215: attrValue = serial;
0216: list.addAll(search(splitString(params
0217: .getSearchForSerialNumberIn()), attrValue, attrs));
0218: }
0219: if (serial == null && subject == null) {
0220: list.addAll(search(attrNames, "*", attrs));
0221: }
0222:
0223: return list;
0224: }
0225:
0226: /**
0227: * Can use the subject of the forward certificate of the set certificate
0228: * pair or the subject of the forward
0229: * {@link org.bouncycastle.x509.X509CertStoreSelector} of the given
0230: * selector.
0231: *
0232: * @param xselector The selector with the search criteria.
0233: * @param attrs Attributes which contain the attribute certificates in the
0234: * LDAP directory.
0235: * @param attrNames Attribute names in the LDAP directory which correspond to the
0236: * subjectAttributeNames.
0237: * @param subjectAttributeNames Subject attribute names (like "CN", "O", "OU") to use to
0238: * search in the LDAP directory
0239: * @return A list of found DER encoded certificate pairs.
0240: * @throws StoreException if an error occurs while searching.
0241: */
0242: private List crossCertificatePairSubjectSearch(
0243: X509CertPairStoreSelector xselector, String[] attrs,
0244: String attrNames[], String subjectAttributeNames[])
0245: throws StoreException {
0246: List list = new ArrayList();
0247:
0248: // search for subject
0249: String subject = null;
0250:
0251: if (xselector.getForwardSelector() != null) {
0252: subject = getSubjectAsString(xselector.getForwardSelector());
0253: }
0254: if (xselector.getCertPair() != null) {
0255: if (xselector.getCertPair().getForward() != null) {
0256: subject = xselector.getCertPair().getForward()
0257: .getSubjectX500Principal().getName("RFC1779");
0258: }
0259: }
0260: String attrValue = null;
0261: if (subject != null) {
0262: for (int i = 0; i < subjectAttributeNames.length; i++) {
0263: attrValue = parseDN(subject, subjectAttributeNames[i]);
0264: list.addAll(search(attrNames, "*" + attrValue + "*",
0265: attrs));
0266: }
0267: }
0268: if (subject == null) {
0269: list.addAll(search(attrNames, "*", attrs));
0270: }
0271:
0272: return list;
0273: }
0274:
0275: /**
0276: * Can use the entityName of the holder of the attribute certificate, the
0277: * serialNumber of attribute certificate and the serialNumber of the
0278: * associated certificate of the given of the X509AttributeCertSelector.
0279: *
0280: * @param xselector The selector with the search criteria.
0281: * @param attrs Attributes which contain the attribute certificates in the
0282: * LDAP directory.
0283: * @param attrNames Attribute names in the LDAP directory which correspond to the
0284: * subjectAttributeNames.
0285: * @param subjectAttributeNames Subject attribute names (like "CN", "O", "OU") to use to
0286: * search in the LDAP directory
0287: * @return A list of found DER encoded attribute certificates.
0288: * @throws StoreException if an error occurs while searching.
0289: */
0290: private List attrCertSubjectSerialSearch(
0291: X509AttributeCertStoreSelector xselector, String[] attrs,
0292: String attrNames[], String subjectAttributeNames[])
0293: throws StoreException {
0294: List list = new ArrayList();
0295:
0296: // search for serialNumber of associated cert,
0297: // serialNumber of the attribute certificate or DN in the entityName
0298: // of the holder
0299:
0300: String subject = null;
0301: String serial = null;
0302:
0303: Collection serials = new HashSet();
0304: Principal principals[] = null;
0305: if (xselector.getHolder() != null) {
0306: // serialNumber of associated cert
0307: if (xselector.getHolder().getSerialNumber() != null) {
0308: serials.add(xselector.getHolder().getSerialNumber()
0309: .toString());
0310: }
0311: // DN in the entityName of the holder
0312: if (xselector.getHolder().getEntityNames() != null) {
0313: principals = xselector.getHolder().getEntityNames();
0314: }
0315: }
0316:
0317: if (xselector.getAttributeCert() != null) {
0318: if (xselector.getAttributeCert().getHolder()
0319: .getEntityNames() != null) {
0320: principals = xselector.getAttributeCert().getHolder()
0321: .getEntityNames();
0322: }
0323: // serialNumber of the attribute certificate
0324: serials.add(xselector.getAttributeCert().getSerialNumber()
0325: .toString());
0326: }
0327: if (principals != null) {
0328: // only first should be relevant
0329: if (principals[0] instanceof X500Principal) {
0330: subject = ((X500Principal) principals[0])
0331: .getName("RFC1779");
0332: } else {
0333: // strange ...
0334: subject = principals[0].getName();
0335: }
0336: }
0337: if (xselector.getSerialNumber() != null) {
0338: serials.add(xselector.getSerialNumber().toString());
0339: }
0340:
0341: String attrValue = null;
0342: if (subject != null) {
0343: for (int i = 0; i < subjectAttributeNames.length; i++) {
0344: attrValue = parseDN(subject, subjectAttributeNames[i]);
0345: list.addAll(search(attrNames, "*" + attrValue + "*",
0346: attrs));
0347: }
0348: }
0349: if (serials.size() > 0
0350: && params.getSearchForSerialNumberIn() != null) {
0351: Iterator it = serials.iterator();
0352: while (it.hasNext()) {
0353: serial = (String) it.next();
0354: list.addAll(search(splitString(params
0355: .getSearchForSerialNumberIn()), serial, attrs));
0356: }
0357: }
0358: if (serials.size() == 0 && subject == null) {
0359: list.addAll(search(attrNames, "*", attrs));
0360: }
0361:
0362: return list;
0363: }
0364:
0365: /**
0366: * Can use the issuer of the given of the X509CRLStoreSelector.
0367: *
0368: * @param xselector The selector with the search criteria.
0369: * @param attrs Attributes which contain the attribute certificates in the
0370: * LDAP directory.
0371: * @param attrNames Attribute names in the LDAP directory which correspond to the
0372: * subjectAttributeNames.
0373: * @param issuerAttributeNames Issuer attribute names (like "CN", "O", "OU") to use to search
0374: * in the LDAP directory
0375: * @return A list of found DER encoded CRLs.
0376: * @throws StoreException if an error occurs while searching.
0377: */
0378: private List cRLIssuerSearch(X509CRLStoreSelector xselector,
0379: String[] attrs, String attrNames[],
0380: String issuerAttributeNames[]) throws StoreException {
0381: List list = new ArrayList();
0382:
0383: String issuer = null;
0384: Collection issuers = new HashSet();
0385: if (xselector.getIssuers() != null) {
0386: issuers.addAll(xselector.getIssuers());
0387: }
0388: if (xselector.getCertificateChecking() != null) {
0389: issuers.add(getCertificateIssuer(xselector
0390: .getCertificateChecking()));
0391: }
0392: if (xselector.getAttrCertificateChecking() != null) {
0393: Principal principals[] = xselector
0394: .getAttrCertificateChecking().getIssuer()
0395: .getPrincipals();
0396: for (int i = 0; i < principals.length; i++) {
0397: if (principals[i] instanceof X500Principal) {
0398: issuers.add(principals[i]);
0399: }
0400: }
0401: }
0402: Iterator it = issuers.iterator();
0403: while (it.hasNext()) {
0404: issuer = ((X500Principal) it.next()).getName("RFC1779");
0405: String attrValue = null;
0406:
0407: for (int i = 0; i < issuerAttributeNames.length; i++) {
0408: attrValue = parseDN(issuer, issuerAttributeNames[i]);
0409: list.addAll(search(attrNames, "*" + attrValue + "*",
0410: attrs));
0411: }
0412: }
0413: if (issuer == null) {
0414: list.addAll(search(attrNames, "*", attrs));
0415: }
0416:
0417: return list;
0418: }
0419:
0420: /**
0421: * Returns a <code>List</code> of encodings of the certificates, attribute
0422: * certificates, CRL or certificate pairs.
0423: *
0424: * @param attributeNames The attribute names to look for in the LDAP.
0425: * @param attributeValue The value the attribute name must have.
0426: * @param attrs The attributes in the LDAP which hold the certificate,
0427: * attribute certificate, certificate pair or CRL in a found
0428: * entry.
0429: * @return A <code>List</code> of byte arrays with the encodings.
0430: * @throws StoreException if an error occurs getting the results from the LDAP
0431: * directory.
0432: */
0433: private List search(String attributeNames[], String attributeValue,
0434: String[] attrs) throws StoreException {
0435: String filter = null;
0436: if (attributeNames == null) {
0437: filter = null;
0438: } else {
0439: filter = "";
0440: if (attributeValue.equals("**")) {
0441: attributeValue = "*";
0442: }
0443: for (int i = 0; i < attributeNames.length; i++) {
0444: filter += "(" + attributeNames[i] + "="
0445: + attributeValue + ")";
0446: }
0447: filter = "(|" + filter + ")";
0448: }
0449: String filter2 = "";
0450: for (int i = 0; i < attrs.length; i++) {
0451: filter2 += "(" + attrs[i] + "=*)";
0452: }
0453: filter2 = "(|" + filter2 + ")";
0454:
0455: String filter3 = "(&" + filter + "" + filter2 + ")";
0456: if (filter == null) {
0457: filter3 = filter2;
0458: }
0459: List list;
0460: list = getFromCache(filter3);
0461: if (list != null) {
0462: return list;
0463: }
0464: DirContext ctx = null;
0465: list = new ArrayList();
0466: try {
0467:
0468: ctx = connectLDAP();
0469:
0470: SearchControls constraints = new SearchControls();
0471: constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
0472: constraints.setCountLimit(0);
0473: constraints.setReturningAttributes(attrs);
0474: NamingEnumeration results = ctx.search(params.getBaseDN(),
0475: filter3, constraints);
0476: while (results.hasMoreElements()) {
0477: SearchResult sr = (SearchResult) results.next();
0478: NamingEnumeration enumeration = ((Attribute) (sr
0479: .getAttributes().getAll().next())).getAll();
0480: while (enumeration.hasMore()) {
0481: list.add(enumeration.next());
0482: }
0483: }
0484: addToCache(filter3, list);
0485: } catch (NamingException e) {
0486: // skip exception, unfortunately if an attribute type is not
0487: // supported an exception is thrown
0488:
0489: } finally {
0490: try {
0491: if (null != ctx) {
0492: ctx.close();
0493: }
0494: } catch (Exception e) {
0495: }
0496: }
0497: return list;
0498: }
0499:
0500: private Set createCRLs(List list, X509CRLStoreSelector xselector)
0501: throws StoreException {
0502: Set crlSet = new HashSet();
0503:
0504: X509CRLParser parser = new X509CRLParser();
0505: Iterator it = list.iterator();
0506: while (it.hasNext()) {
0507: try {
0508: parser.engineInit(new ByteArrayInputStream((byte[]) it
0509: .next()));
0510: X509CRL crl = (X509CRL) parser.engineRead();
0511: if (xselector.match((Object) crl)) {
0512: crlSet.add(crl);
0513: }
0514: } catch (StreamParsingException e) {
0515:
0516: }
0517: }
0518:
0519: return crlSet;
0520: }
0521:
0522: private Set createCrossCertificatePairs(List list,
0523: X509CertPairStoreSelector xselector) throws StoreException {
0524: Set certPairSet = new HashSet();
0525:
0526: int i = 0;
0527: while (i < list.size()) {
0528: X509CertificatePair pair;
0529: try {
0530: // first try to decode it as certificate pair
0531: try {
0532: X509CertPairParser parser = new X509CertPairParser();
0533: parser.engineInit(new ByteArrayInputStream(
0534: (byte[]) list.get(i)));
0535: pair = (X509CertificatePair) parser.engineRead();
0536: } catch (StreamParsingException e) {
0537: // now try it to construct it the forward and reverse
0538: // certificate
0539: byte[] forward = (byte[]) list.get(i);
0540: byte[] reverse = (byte[]) list.get(i + 1);
0541: pair = new X509CertificatePair(new CertificatePair(
0542: X509CertificateStructure
0543: .getInstance(new ASN1InputStream(
0544: forward).readObject()),
0545: X509CertificateStructure
0546: .getInstance(new ASN1InputStream(
0547: reverse).readObject())));
0548: i++;
0549: }
0550: if (xselector.match((Object) pair)) {
0551: certPairSet.add(pair);
0552: }
0553: } catch (CertificateParsingException e) {
0554: // try next
0555: } catch (IOException e) {
0556: // try next
0557: }
0558: i++;
0559: }
0560:
0561: return certPairSet;
0562: }
0563:
0564: private Set createAttributeCertificates(List list,
0565: X509AttributeCertStoreSelector xselector)
0566: throws StoreException {
0567: Set certSet = new HashSet();
0568:
0569: Iterator it = list.iterator();
0570: X509AttrCertParser parser = new X509AttrCertParser();
0571: while (it.hasNext()) {
0572: try {
0573: parser.engineInit(new ByteArrayInputStream((byte[]) it
0574: .next()));
0575: X509AttributeCertificate cert = (X509AttributeCertificate) parser
0576: .engineRead();
0577: if (xselector.match((Object) cert)) {
0578: certSet.add(cert);
0579: }
0580: } catch (StreamParsingException e) {
0581:
0582: }
0583: }
0584:
0585: return certSet;
0586: }
0587:
0588: /**
0589: * Returns the CRLs for issued certificates for other CAs matching the given
0590: * selector. <br>
0591: * The authorityRevocationList attribute includes revocation information
0592: * regarding certificates issued to other CAs.
0593: *
0594: * @param selector The CRL selector to use to find the CRLs.
0595: * @return A possible empty collection with CRLs
0596: * @throws StoreException
0597: */
0598: public Collection getAuthorityRevocationLists(
0599: X509CRLStoreSelector selector) throws StoreException {
0600: String[] attrs = splitString(params
0601: .getAuthorityRevocationListAttribute());
0602: String attrNames[] = splitString(params
0603: .getLdapAuthorityRevocationListAttributeName());
0604: String issuerAttributeNames[] = splitString(params
0605: .getAuthorityRevocationListIssuerAttributeName());
0606:
0607: List list = cRLIssuerSearch(selector, attrs, attrNames,
0608: issuerAttributeNames);
0609: Set resultSet = createCRLs(list, selector);
0610: if (resultSet.size() == 0) {
0611: X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
0612: list = cRLIssuerSearch(emptySelector, attrs, attrNames,
0613: issuerAttributeNames);
0614:
0615: resultSet.addAll(createCRLs(list, selector));
0616: }
0617: return resultSet;
0618: }
0619:
0620: /**
0621: * Returns the revocation list for revoked attribute certificates.
0622: * <p/>
0623: * The attributeCertificateRevocationList holds a list of attribute
0624: * certificates that have been revoked.
0625: *
0626: * @param selector The CRL selector to use to find the CRLs.
0627: * @return A possible empty collection with CRLs.
0628: * @throws StoreException
0629: */
0630: public Collection getAttributeCertificateRevocationLists(
0631: X509CRLStoreSelector selector) throws StoreException {
0632: String[] attrs = splitString(params
0633: .getAttributeCertificateRevocationListAttribute());
0634: String attrNames[] = splitString(params
0635: .getLdapAttributeCertificateRevocationListAttributeName());
0636: String issuerAttributeNames[] = splitString(params
0637: .getAttributeCertificateRevocationListIssuerAttributeName());
0638:
0639: List list = cRLIssuerSearch(selector, attrs, attrNames,
0640: issuerAttributeNames);
0641: Set resultSet = createCRLs(list, selector);
0642: if (resultSet.size() == 0) {
0643: X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
0644: list = cRLIssuerSearch(emptySelector, attrs, attrNames,
0645: issuerAttributeNames);
0646:
0647: resultSet.addAll(createCRLs(list, selector));
0648: }
0649: return resultSet;
0650: }
0651:
0652: /**
0653: * Returns the revocation list for revoked attribute certificates for an
0654: * attribute authority
0655: * <p/>
0656: * The attributeAuthorityList holds a list of AA certificates that have been
0657: * revoked.
0658: *
0659: * @param selector The CRL selector to use to find the CRLs.
0660: * @return A possible empty collection with CRLs
0661: * @throws StoreException
0662: */
0663: public Collection getAttributeAuthorityRevocationLists(
0664: X509CRLStoreSelector selector) throws StoreException {
0665: String[] attrs = splitString(params
0666: .getAttributeAuthorityRevocationListAttribute());
0667: String attrNames[] = splitString(params
0668: .getLdapAttributeAuthorityRevocationListAttributeName());
0669: String issuerAttributeNames[] = splitString(params
0670: .getAttributeAuthorityRevocationListIssuerAttributeName());
0671:
0672: List list = cRLIssuerSearch(selector, attrs, attrNames,
0673: issuerAttributeNames);
0674: Set resultSet = createCRLs(list, selector);
0675: if (resultSet.size() == 0) {
0676: X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
0677: list = cRLIssuerSearch(emptySelector, attrs, attrNames,
0678: issuerAttributeNames);
0679:
0680: resultSet.addAll(createCRLs(list, selector));
0681: }
0682: return resultSet;
0683: }
0684:
0685: /**
0686: * Returns cross certificate pairs.
0687: *
0688: * @param selector The selector to use to find the cross certificates.
0689: * @return A possible empty collection with {@link X509CertificatePair}s
0690: * @throws StoreException
0691: */
0692: public Collection getCrossCertificatePairs(
0693: X509CertPairStoreSelector selector) throws StoreException {
0694: String[] attrs = splitString(params
0695: .getCrossCertificateAttribute());
0696: String attrNames[] = splitString(params
0697: .getLdapCrossCertificateAttributeName());
0698: String subjectAttributeNames[] = splitString(params
0699: .getCrossCertificateSubjectAttributeName());
0700: List list = crossCertificatePairSubjectSearch(selector, attrs,
0701: attrNames, subjectAttributeNames);
0702: Set resultSet = createCrossCertificatePairs(list, selector);
0703: if (resultSet.size() == 0) {
0704: X509CertStoreSelector emptyCertselector = new X509CertStoreSelector();
0705: X509CertPairStoreSelector emptySelector = new X509CertPairStoreSelector();
0706:
0707: emptySelector.setForwardSelector(emptyCertselector);
0708: emptySelector.setReverseSelector(emptyCertselector);
0709: list = crossCertificatePairSubjectSearch(emptySelector,
0710: attrs, attrNames, subjectAttributeNames);
0711: resultSet
0712: .addAll(createCrossCertificatePairs(list, selector));
0713: }
0714: return resultSet;
0715: }
0716:
0717: /**
0718: * Returns end certificates.
0719: * <p/>
0720: * The attributeDescriptorCertificate is self signed by a source of
0721: * authority and holds a description of the privilege and its delegation
0722: * rules.
0723: *
0724: * @param selector The selector to find the certificates.
0725: * @return A possible empty collection with certificates.
0726: * @throws StoreException
0727: */
0728: public Collection getUserCertificates(X509CertStoreSelector selector)
0729: throws StoreException {
0730: String[] attrs = splitString(params
0731: .getUserCertificateAttribute());
0732: String attrNames[] = splitString(params
0733: .getLdapUserCertificateAttributeName());
0734: String subjectAttributeNames[] = splitString(params
0735: .getUserCertificateSubjectAttributeName());
0736:
0737: List list = certSubjectSerialSearch(selector, attrs, attrNames,
0738: subjectAttributeNames);
0739: Set resultSet = createCerts(list, selector);
0740: if (resultSet.size() == 0) {
0741: X509CertStoreSelector emptySelector = new X509CertStoreSelector();
0742: list = certSubjectSerialSearch(emptySelector, attrs,
0743: attrNames, subjectAttributeNames);
0744: resultSet.addAll(createCerts(list, selector));
0745: }
0746:
0747: return resultSet;
0748: }
0749:
0750: /**
0751: * Returns attribute certificates for an attribute authority
0752: * <p/>
0753: * The aAcertificate holds the privileges of an attribute authority.
0754: *
0755: * @param selector The selector to find the attribute certificates.
0756: * @return A possible empty collection with attribute certificates.
0757: * @throws StoreException
0758: */
0759: public Collection getAACertificates(
0760: X509AttributeCertStoreSelector selector)
0761: throws StoreException {
0762: String[] attrs = splitString(params.getAACertificateAttribute());
0763: String attrNames[] = splitString(params
0764: .getLdapAACertificateAttributeName());
0765: String subjectAttributeNames[] = splitString(params
0766: .getAACertificateSubjectAttributeName());
0767:
0768: List list = attrCertSubjectSerialSearch(selector, attrs,
0769: attrNames, subjectAttributeNames);
0770: Set resultSet = createAttributeCertificates(list, selector);
0771: if (resultSet.size() == 0) {
0772: X509AttributeCertStoreSelector emptySelector = new X509AttributeCertStoreSelector();
0773: list = attrCertSubjectSerialSearch(emptySelector, attrs,
0774: attrNames, subjectAttributeNames);
0775: resultSet
0776: .addAll(createAttributeCertificates(list, selector));
0777: }
0778:
0779: return resultSet;
0780: }
0781:
0782: /**
0783: * Returns an attribute certificate for an authority
0784: * <p/>
0785: * The attributeDescriptorCertificate is self signed by a source of
0786: * authority and holds a description of the privilege and its delegation
0787: * rules.
0788: *
0789: * @param selector The selector to find the attribute certificates.
0790: * @return A possible empty collection with attribute certificates.
0791: * @throws StoreException
0792: */
0793: public Collection getAttributeDescriptorCertificates(
0794: X509AttributeCertStoreSelector selector)
0795: throws StoreException {
0796: String[] attrs = splitString(params
0797: .getAttributeDescriptorCertificateAttribute());
0798: String attrNames[] = splitString(params
0799: .getLdapAttributeDescriptorCertificateAttributeName());
0800: String subjectAttributeNames[] = splitString(params
0801: .getAttributeDescriptorCertificateSubjectAttributeName());
0802:
0803: List list = attrCertSubjectSerialSearch(selector, attrs,
0804: attrNames, subjectAttributeNames);
0805: Set resultSet = createAttributeCertificates(list, selector);
0806: if (resultSet.size() == 0) {
0807: X509AttributeCertStoreSelector emptySelector = new X509AttributeCertStoreSelector();
0808: list = attrCertSubjectSerialSearch(emptySelector, attrs,
0809: attrNames, subjectAttributeNames);
0810: resultSet
0811: .addAll(createAttributeCertificates(list, selector));
0812: }
0813:
0814: return resultSet;
0815: }
0816:
0817: /**
0818: * Returns CA certificates.
0819: * <p/>
0820: * The cACertificate attribute of a CA's directory entry shall be used to
0821: * store self-issued certificates (if any) and certificates issued to this
0822: * CA by CAs in the same realm as this CA.
0823: *
0824: * @param selector The selector to find the certificates.
0825: * @return A possible empty collection with certificates.
0826: * @throws StoreException
0827: */
0828: public Collection getCACertificates(X509CertStoreSelector selector)
0829: throws StoreException {
0830: String[] attrs = splitString(params.getCACertificateAttribute());
0831: String attrNames[] = splitString(params
0832: .getLdapCACertificateAttributeName());
0833: String subjectAttributeNames[] = splitString(params
0834: .getCACertificateSubjectAttributeName());
0835: List list = certSubjectSerialSearch(selector, attrs, attrNames,
0836: subjectAttributeNames);
0837: Set resultSet = createCerts(list, selector);
0838: if (resultSet.size() == 0) {
0839: X509CertStoreSelector emptySelector = new X509CertStoreSelector();
0840: list = certSubjectSerialSearch(emptySelector, attrs,
0841: attrNames, subjectAttributeNames);
0842: resultSet.addAll(createCerts(list, selector));
0843: }
0844: return resultSet;
0845: }
0846:
0847: /**
0848: * Returns the delta revocation list for revoked certificates.
0849: *
0850: * @param selector The CRL selector to use to find the CRLs.
0851: * @return A possible empty collection with CRLs.
0852: * @throws StoreException
0853: */
0854: public Collection getDeltaCertificateRevocationLists(
0855: X509CRLStoreSelector selector) throws StoreException {
0856: String[] attrs = splitString(params
0857: .getDeltaRevocationListAttribute());
0858: String attrNames[] = splitString(params
0859: .getLdapDeltaRevocationListAttributeName());
0860: String issuerAttributeNames[] = splitString(params
0861: .getDeltaRevocationListIssuerAttributeName());
0862: List list = cRLIssuerSearch(selector, attrs, attrNames,
0863: issuerAttributeNames);
0864: Set resultSet = createCRLs(list, selector);
0865: if (resultSet.size() == 0) {
0866: X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
0867: list = cRLIssuerSearch(emptySelector, attrs, attrNames,
0868: issuerAttributeNames);
0869:
0870: resultSet.addAll(createCRLs(list, selector));
0871: }
0872: return resultSet;
0873: }
0874:
0875: /**
0876: * Returns an attribute certificate for an user.
0877: * <p/>
0878: * The attributeCertificateAttribute holds the privileges of a user
0879: *
0880: * @param selector The selector to find the attribute certificates.
0881: * @return A possible empty collection with attribute certificates.
0882: * @throws StoreException
0883: */
0884: public Collection getAttributeCertificateAttributes(
0885: X509AttributeCertStoreSelector selector)
0886: throws StoreException {
0887: String[] attrs = splitString(params
0888: .getAttributeCertificateAttributeAttribute());
0889: String attrNames[] = splitString(params
0890: .getLdapAttributeCertificateAttributeAttributeName());
0891: String subjectAttributeNames[] = splitString(params
0892: .getAttributeCertificateAttributeSubjectAttributeName());
0893: List list = attrCertSubjectSerialSearch(selector, attrs,
0894: attrNames, subjectAttributeNames);
0895: Set resultSet = createAttributeCertificates(list, selector);
0896: if (resultSet.size() == 0) {
0897: X509AttributeCertStoreSelector emptySelector = new X509AttributeCertStoreSelector();
0898: list = attrCertSubjectSerialSearch(emptySelector, attrs,
0899: attrNames, subjectAttributeNames);
0900: resultSet
0901: .addAll(createAttributeCertificates(list, selector));
0902: }
0903:
0904: return resultSet;
0905: }
0906:
0907: /**
0908: * Returns the certificate revocation lists for revoked certificates.
0909: *
0910: * @param selector The CRL selector to use to find the CRLs.
0911: * @return A possible empty collection with CRLs.
0912: * @throws StoreException
0913: */
0914: public Collection getCertificateRevocationLists(
0915: X509CRLStoreSelector selector) throws StoreException {
0916: String[] attrs = splitString(params
0917: .getCertificateRevocationListAttribute());
0918: String attrNames[] = splitString(params
0919: .getLdapCertificateRevocationListAttributeName());
0920: String issuerAttributeNames[] = splitString(params
0921: .getCertificateRevocationListIssuerAttributeName());
0922: List list = cRLIssuerSearch(selector, attrs, attrNames,
0923: issuerAttributeNames);
0924: Set resultSet = createCRLs(list, selector);
0925: if (resultSet.size() == 0) {
0926: X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
0927: list = cRLIssuerSearch(emptySelector, attrs, attrNames,
0928: issuerAttributeNames);
0929:
0930: resultSet.addAll(createCRLs(list, selector));
0931: }
0932: return resultSet;
0933: }
0934:
0935: private Map cacheMap = new HashMap(cacheSize);
0936:
0937: private static int cacheSize = 32;
0938:
0939: private static long lifeTime = 60 * 1000;
0940:
0941: private synchronized void addToCache(String searchCriteria,
0942: List list) {
0943: Date now = new Date(System.currentTimeMillis());
0944: List cacheEntry = new ArrayList();
0945: cacheEntry.add(now);
0946: cacheEntry.add(list);
0947: if (cacheMap.containsKey(searchCriteria)) {
0948: cacheMap.put(searchCriteria, cacheEntry);
0949: } else {
0950: if (cacheMap.size() >= cacheSize) {
0951: // replace oldest
0952: Iterator it = cacheMap.entrySet().iterator();
0953: long oldest = now.getTime();
0954: Object replace = null;
0955: while (it.hasNext()) {
0956: Map.Entry entry = (Map.Entry) it.next();
0957: long current = ((Date) ((List) entry.getValue())
0958: .get(0)).getTime();
0959: if (current < oldest) {
0960: oldest = current;
0961: replace = entry.getKey();
0962: }
0963: }
0964: cacheMap.remove(replace);
0965: }
0966: cacheMap.put(searchCriteria, cacheEntry);
0967: }
0968: }
0969:
0970: private List getFromCache(String searchCriteria) {
0971: List entry = (List) cacheMap.get(searchCriteria);
0972: long now = System.currentTimeMillis();
0973: if (entry != null) {
0974: // too old
0975: if (((Date) entry.get(0)).getTime() < (now - lifeTime)) {
0976: return null;
0977: }
0978: return (List) entry.get(1);
0979: }
0980: return null;
0981: }
0982:
0983: /*
0984: * spilt string based on spaces
0985: */
0986: private String[] splitString(String str) {
0987: return str.split("\\s+");
0988: }
0989:
0990: private String getSubjectAsString(X509CertStoreSelector xselector) {
0991: try {
0992: byte[] encSubject = xselector.getSubjectAsBytes();
0993: if (encSubject != null) {
0994: return new X500Principal(encSubject).getName("RFC1779");
0995: }
0996: } catch (IOException e) {
0997: throw new StoreException("exception processing name: "
0998: + e.getMessage(), e);
0999: }
1000: return null;
1001: }
1002:
1003: private X500Principal getCertificateIssuer(X509Certificate cert) {
1004: return cert.getIssuerX500Principal();
1005: }
1006: }
|