blob: 68e450e5eee267e2036e7326bdf2181c398ed13b [file] [log] [blame]
package org.bouncycastle.x509.util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.Principal;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.security.auth.x500.X500Principal;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.x509.Certificate;
import org.bouncycastle.asn1.x509.CertificatePair;
import org.bouncycastle.jce.X509LDAPCertStoreParameters;
import org.bouncycastle.jce.provider.X509AttrCertParser;
import org.bouncycastle.jce.provider.X509CRLParser;
import org.bouncycastle.jce.provider.X509CertPairParser;
import org.bouncycastle.jce.provider.X509CertParser;
import org.bouncycastle.util.StoreException;
import org.bouncycastle.x509.X509AttributeCertStoreSelector;
import org.bouncycastle.x509.X509AttributeCertificate;
import org.bouncycastle.x509.X509CRLStoreSelector;
import org.bouncycastle.x509.X509CertPairStoreSelector;
import org.bouncycastle.x509.X509CertStoreSelector;
import org.bouncycastle.x509.X509CertificatePair;
/**
* This is a general purpose implementation to get X.509 certificates, CRLs,
* attribute certificates and cross certificates from a LDAP location.
* <p>
* At first a search is performed in the ldap*AttributeNames of the
* {@link org.bouncycastle.jce.X509LDAPCertStoreParameters} with the given
* information of the subject (for all kind of certificates) or issuer (for
* CRLs), respectively, if a {@link org.bouncycastle.x509.X509CertStoreSelector} or
* {@link org.bouncycastle.x509.X509AttributeCertificate} is given with that
* details.
* </p><p>
* For the used schemes see:
* <ul>
* <li><a href="http://www.ietf.org/rfc/rfc2587.txt">RFC 2587</a>
* <li><a
* href="http://www3.ietf.org/proceedings/01mar/I-D/pkix-ldap-schema-01.txt">Internet
* X.509 Public Key Infrastructure Additional LDAP Schema for PKIs and PMIs</a>
* </ul>
*/
public class LDAPStoreHelper
{
// TODO: cache results
private X509LDAPCertStoreParameters params;
public LDAPStoreHelper(X509LDAPCertStoreParameters params)
{
this.params = params;
}
/**
* Initial Context Factory.
*/
private static String LDAP_PROVIDER = "com.sun.jndi.ldap.LdapCtxFactory";
/**
* Processing referrals..
*/
private static String REFERRALS_IGNORE = "ignore";
/**
* Security level to be used for LDAP connections.
*/
private static final String SEARCH_SECURITY_LEVEL = "none";
/**
* Package Prefix for loading URL context factories.
*/
private static final String URL_CONTEXT_PREFIX = "com.sun.jndi.url";
private DirContext connectLDAP() throws NamingException
{
Properties props = new Properties();
props.setProperty(Context.INITIAL_CONTEXT_FACTORY, LDAP_PROVIDER);
props.setProperty(Context.BATCHSIZE, "0");
props.setProperty(Context.PROVIDER_URL, params.getLdapURL());
props.setProperty(Context.URL_PKG_PREFIXES, URL_CONTEXT_PREFIX);
props.setProperty(Context.REFERRAL, REFERRALS_IGNORE);
props.setProperty(Context.SECURITY_AUTHENTICATION,
SEARCH_SECURITY_LEVEL);
DirContext ctx = new InitialDirContext(props);
return ctx;
}
private String parseDN(String subject, String dNAttributeName)
{
String temp = subject;
int begin = temp.toLowerCase().indexOf(
dNAttributeName.toLowerCase() + "=");
if (begin == -1)
{
return "";
}
temp = temp.substring(begin + dNAttributeName.length());
int end = temp.indexOf(',');
if (end == -1)
{
end = temp.length();
}
while (temp.charAt(end - 1) == '\\')
{
end = temp.indexOf(',', end + 1);
if (end == -1)
{
end = temp.length();
}
}
temp = temp.substring(0, end);
begin = temp.indexOf('=');
temp = temp.substring(begin + 1);
if (temp.charAt(0) == ' ')
{
temp = temp.substring(1);
}
if (temp.startsWith("\""))
{
temp = temp.substring(1);
}
if (temp.endsWith("\""))
{
temp = temp.substring(0, temp.length() - 1);
}
return temp;
}
private Set createCerts(List list, X509CertStoreSelector xselector)
throws StoreException
{
Set certSet = new HashSet();
Iterator it = list.iterator();
X509CertParser parser = new X509CertParser();
while (it.hasNext())
{
try
{
parser.engineInit(new ByteArrayInputStream((byte[])it
.next()));
X509Certificate cert = (X509Certificate)parser
.engineRead();
if (xselector.match((Object)cert))
{
certSet.add(cert);
}
}
catch (Exception e)
{
}
}
return certSet;
}
/**
* Can use the subject and serial and the subject and serialNumber of the
* certificate of the given of the X509CertStoreSelector. If a certificate
* for checking is given this has higher precedence.
*
* @param xselector The selector with the search criteria.
* @param attrs Attributes which contain the certificates in the LDAP
* directory.
* @param attrNames Attribute names in teh LDAP directory which correspond to the
* subjectAttributeNames.
* @param subjectAttributeNames Subject attribute names (like "CN", "O", "OU") to use to
* search in the LDAP directory
* @return A list of found DER encoded certificates.
* @throws StoreException if an error occurs while searching.
*/
private List certSubjectSerialSearch(X509CertStoreSelector xselector,
String[] attrs, String attrNames[], String subjectAttributeNames[])
throws StoreException
{
// TODO: support also subjectAltNames?
List list = new ArrayList();
String subject = null;
String serial = null;
subject = getSubjectAsString(xselector);
if (xselector.getSerialNumber() != null)
{
serial = xselector.getSerialNumber().toString();
}
if (xselector.getCertificate() != null)
{
subject = xselector.getCertificate().getSubjectX500Principal().getName("RFC1779");
serial = xselector.getCertificate().getSerialNumber().toString();
}
String attrValue = null;
if (subject != null)
{
for (int i = 0; i < subjectAttributeNames.length; i++)
{
attrValue = parseDN(subject, subjectAttributeNames[i]);
list
.addAll(search(attrNames, "*" + attrValue + "*",
attrs));
}
}
if (serial != null && params.getSearchForSerialNumberIn() != null)
{
attrValue = serial;
list.addAll(search(
splitString(params.getSearchForSerialNumberIn()),
attrValue, attrs));
}
if (serial == null && subject == null)
{
list.addAll(search(attrNames, "*", attrs));
}
return list;
}
/**
* Can use the subject of the forward certificate of the set certificate
* pair or the subject of the forward
* {@link org.bouncycastle.x509.X509CertStoreSelector} of the given
* selector.
*
* @param xselector The selector with the search criteria.
* @param attrs Attributes which contain the attribute certificates in the
* LDAP directory.
* @param attrNames Attribute names in the LDAP directory which correspond to the
* subjectAttributeNames.
* @param subjectAttributeNames Subject attribute names (like "CN", "O", "OU") to use to
* search in the LDAP directory
* @return A list of found DER encoded certificate pairs.
* @throws StoreException if an error occurs while searching.
*/
private List crossCertificatePairSubjectSearch(
X509CertPairStoreSelector xselector, String[] attrs,
String attrNames[], String subjectAttributeNames[])
throws StoreException
{
List list = new ArrayList();
// search for subject
String subject = null;
if (xselector.getForwardSelector() != null)
{
subject = getSubjectAsString(xselector.getForwardSelector());
}
if (xselector.getCertPair() != null)
{
if (xselector.getCertPair().getForward() != null)
{
subject = xselector.getCertPair().getForward()
.getSubjectX500Principal().getName("RFC1779");
}
}
String attrValue = null;
if (subject != null)
{
for (int i = 0; i < subjectAttributeNames.length; i++)
{
attrValue = parseDN(subject, subjectAttributeNames[i]);
list
.addAll(search(attrNames, "*" + attrValue + "*",
attrs));
}
}
if (subject == null)
{
list.addAll(search(attrNames, "*", attrs));
}
return list;
}
/**
* Can use the entityName of the holder of the attribute certificate, the
* serialNumber of attribute certificate and the serialNumber of the
* associated certificate of the given of the X509AttributeCertSelector.
*
* @param xselector The selector with the search criteria.
* @param attrs Attributes which contain the attribute certificates in the
* LDAP directory.
* @param attrNames Attribute names in the LDAP directory which correspond to the
* subjectAttributeNames.
* @param subjectAttributeNames Subject attribute names (like "CN", "O", "OU") to use to
* search in the LDAP directory
* @return A list of found DER encoded attribute certificates.
* @throws StoreException if an error occurs while searching.
*/
private List attrCertSubjectSerialSearch(
X509AttributeCertStoreSelector xselector, String[] attrs,
String attrNames[], String subjectAttributeNames[])
throws StoreException
{
List list = new ArrayList();
// search for serialNumber of associated cert,
// serialNumber of the attribute certificate or DN in the entityName
// of the holder
String subject = null;
String serial = null;
Collection serials = new HashSet();
Principal principals[] = null;
if (xselector.getHolder() != null)
{
// serialNumber of associated cert
if (xselector.getHolder().getSerialNumber() != null)
{
serials.add(xselector.getHolder().getSerialNumber()
.toString());
}
// DN in the entityName of the holder
if (xselector.getHolder().getEntityNames() != null)
{
principals = xselector.getHolder().getEntityNames();
}
}
if (xselector.getAttributeCert() != null)
{
if (xselector.getAttributeCert().getHolder().getEntityNames() != null)
{
principals = xselector.getAttributeCert().getHolder()
.getEntityNames();
}
// serialNumber of the attribute certificate
serials.add(xselector.getAttributeCert().getSerialNumber()
.toString());
}
if (principals != null)
{
// only first should be relevant
if (principals[0] instanceof X500Principal)
{
subject = ((X500Principal)principals[0])
.getName("RFC1779");
}
else
{
// strange ...
subject = principals[0].getName();
}
}
if (xselector.getSerialNumber() != null)
{
serials.add(xselector.getSerialNumber().toString());
}
String attrValue = null;
if (subject != null)
{
for (int i = 0; i < subjectAttributeNames.length; i++)
{
attrValue = parseDN(subject, subjectAttributeNames[i]);
list
.addAll(search(attrNames, "*" + attrValue + "*",
attrs));
}
}
if (serials.size() > 0
&& params.getSearchForSerialNumberIn() != null)
{
Iterator it = serials.iterator();
while (it.hasNext())
{
serial = (String)it.next();
list.addAll(search(splitString(params.getSearchForSerialNumberIn()), serial, attrs));
}
}
if (serials.size() == 0 && subject == null)
{
list.addAll(search(attrNames, "*", attrs));
}
return list;
}
/**
* Can use the issuer of the given of the X509CRLStoreSelector.
*
* @param xselector The selector with the search criteria.
* @param attrs Attributes which contain the attribute certificates in the
* LDAP directory.
* @param attrNames Attribute names in the LDAP directory which correspond to the
* subjectAttributeNames.
* @param issuerAttributeNames Issuer attribute names (like "CN", "O", "OU") to use to search
* in the LDAP directory
* @return A list of found DER encoded CRLs.
* @throws StoreException if an error occurs while searching.
*/
private List cRLIssuerSearch(X509CRLStoreSelector xselector,
String[] attrs, String attrNames[], String issuerAttributeNames[])
throws StoreException
{
List list = new ArrayList();
String issuer = null;
Collection issuers = new HashSet();
if (xselector.getIssuers() != null)
{
issuers.addAll(xselector.getIssuers());
}
if (xselector.getCertificateChecking() != null)
{
issuers.add(getCertificateIssuer(xselector.getCertificateChecking()));
}
if (xselector.getAttrCertificateChecking() != null)
{
Principal principals[] = xselector.getAttrCertificateChecking().getIssuer().getPrincipals();
for (int i=0; i<principals.length; i++)
{
if (principals[i] instanceof X500Principal)
{
issuers.add(principals[i]);
}
}
}
Iterator it = issuers.iterator();
while (it.hasNext())
{
issuer = ((X500Principal)it.next()).getName("RFC1779");
String attrValue = null;
for (int i = 0; i < issuerAttributeNames.length; i++)
{
attrValue = parseDN(issuer, issuerAttributeNames[i]);
list
.addAll(search(attrNames, "*" + attrValue + "*",
attrs));
}
}
if (issuer == null)
{
list.addAll(search(attrNames, "*", attrs));
}
return list;
}
/**
* Returns a <code>List</code> of encodings of the certificates, attribute
* certificates, CRL or certificate pairs.
*
* @param attributeNames The attribute names to look for in the LDAP.
* @param attributeValue The value the attribute name must have.
* @param attrs The attributes in the LDAP which hold the certificate,
* attribute certificate, certificate pair or CRL in a found
* entry.
* @return A <code>List</code> of byte arrays with the encodings.
* @throws StoreException if an error occurs getting the results from the LDAP
* directory.
*/
private List search(String attributeNames[], String attributeValue,
String[] attrs) throws StoreException
{
String filter = null;
if (attributeNames == null)
{
filter = null;
}
else
{
filter = "";
if (attributeValue.equals("**"))
{
attributeValue = "*";
}
for (int i = 0; i < attributeNames.length; i++)
{
filter += "(" + attributeNames[i] + "=" + attributeValue + ")";
}
filter = "(|" + filter + ")";
}
String filter2 = "";
for (int i = 0; i < attrs.length; i++)
{
filter2 += "(" + attrs[i] + "=*)";
}
filter2 = "(|" + filter2 + ")";
String filter3 = "(&" + filter + "" + filter2 + ")";
if (filter == null)
{
filter3 = filter2;
}
List list;
list = getFromCache(filter3);
if (list != null)
{
return list;
}
DirContext ctx = null;
list = new ArrayList();
try
{
ctx = connectLDAP();
SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
constraints.setCountLimit(0);
constraints.setReturningAttributes(attrs);
NamingEnumeration results = ctx.search(params.getBaseDN(), filter3,
constraints);
while (results.hasMoreElements())
{
SearchResult sr = (SearchResult)results.next();
NamingEnumeration enumeration = ((Attribute)(sr
.getAttributes().getAll().next())).getAll();
while (enumeration.hasMore())
{
list.add(enumeration.next());
}
}
addToCache(filter3, list);
}
catch (NamingException e)
{
// skip exception, unfortunately if an attribute type is not
// supported an exception is thrown
}
finally
{
try
{
if (null != ctx)
{
ctx.close();
}
}
catch (Exception e)
{
}
}
return list;
}
private Set createCRLs(List list, X509CRLStoreSelector xselector)
throws StoreException
{
Set crlSet = new HashSet();
X509CRLParser parser = new X509CRLParser();
Iterator it = list.iterator();
while (it.hasNext())
{
try
{
parser.engineInit(new ByteArrayInputStream((byte[])it
.next()));
X509CRL crl = (X509CRL)parser.engineRead();
if (xselector.match((Object)crl))
{
crlSet.add(crl);
}
}
catch (StreamParsingException e)
{
}
}
return crlSet;
}
private Set createCrossCertificatePairs(List list,
X509CertPairStoreSelector xselector) throws StoreException
{
Set certPairSet = new HashSet();
int i = 0;
while (i < list.size())
{
X509CertificatePair pair;
try
{
// first try to decode it as certificate pair
try
{
X509CertPairParser parser = new X509CertPairParser();
parser.engineInit(new ByteArrayInputStream(
(byte[])list.get(i)));
pair = (X509CertificatePair)parser.engineRead();
}
catch (StreamParsingException e)
{
// now try it to construct it the forward and reverse
// certificate
byte[] forward = (byte[])list.get(i);
byte[] reverse = (byte[])list.get(i + 1);
pair = new X509CertificatePair(new CertificatePair(
Certificate
.getInstance(new ASN1InputStream(
forward).readObject()),
Certificate
.getInstance(new ASN1InputStream(
reverse).readObject())));
i++;
}
if (xselector.match((Object)pair))
{
certPairSet.add(pair);
}
}
catch (CertificateParsingException e)
{
// try next
}
catch (IOException e)
{
// try next
}
i++;
}
return certPairSet;
}
private Set createAttributeCertificates(List list,
X509AttributeCertStoreSelector xselector) throws StoreException
{
Set certSet = new HashSet();
Iterator it = list.iterator();
X509AttrCertParser parser = new X509AttrCertParser();
while (it.hasNext())
{
try
{
parser.engineInit(new ByteArrayInputStream((byte[])it
.next()));
X509AttributeCertificate cert = (X509AttributeCertificate)parser
.engineRead();
if (xselector.match((Object)cert))
{
certSet.add(cert);
}
}
catch (StreamParsingException e)
{
}
}
return certSet;
}
/**
* Returns the CRLs for issued certificates for other CAs matching the given
* selector. <br>
* The authorityRevocationList attribute includes revocation information
* regarding certificates issued to other CAs.
*
* @param selector The CRL selector to use to find the CRLs.
* @return A possible empty collection with CRLs
* @throws StoreException
*/
public Collection getAuthorityRevocationLists(X509CRLStoreSelector selector)
throws StoreException
{
String[] attrs = splitString(params.getAuthorityRevocationListAttribute());
String attrNames[] = splitString(params
.getLdapAuthorityRevocationListAttributeName());
String issuerAttributeNames[] = splitString(params
.getAuthorityRevocationListIssuerAttributeName());
List list = cRLIssuerSearch(selector, attrs, attrNames,
issuerAttributeNames);
Set resultSet = createCRLs(list, selector);
if (resultSet.size() == 0)
{
X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
list = cRLIssuerSearch(emptySelector, attrs, attrNames,
issuerAttributeNames);
resultSet.addAll(createCRLs(list, selector));
}
return resultSet;
}
/**
* Returns the revocation list for revoked attribute certificates.
* <p>
* The attributeCertificateRevocationList holds a list of attribute
* certificates that have been revoked.
* </p>
* @param selector The CRL selector to use to find the CRLs.
* @return A possible empty collection with CRLs.
* @throws StoreException
*/
public Collection getAttributeCertificateRevocationLists(
X509CRLStoreSelector selector) throws StoreException
{
String[] attrs = splitString(params
.getAttributeCertificateRevocationListAttribute());
String attrNames[] = splitString(params
.getLdapAttributeCertificateRevocationListAttributeName());
String issuerAttributeNames[] = splitString(params
.getAttributeCertificateRevocationListIssuerAttributeName());
List list = cRLIssuerSearch(selector, attrs, attrNames,
issuerAttributeNames);
Set resultSet = createCRLs(list, selector);
if (resultSet.size() == 0)
{
X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
list = cRLIssuerSearch(emptySelector, attrs, attrNames,
issuerAttributeNames);
resultSet.addAll(createCRLs(list, selector));
}
return resultSet;
}
/**
* Returns the revocation list for revoked attribute certificates for an
* attribute authority
* <p>
* The attributeAuthorityList holds a list of AA certificates that have been
* revoked.
* </p>
* @param selector The CRL selector to use to find the CRLs.
* @return A possible empty collection with CRLs
* @throws StoreException
*/
public Collection getAttributeAuthorityRevocationLists(
X509CRLStoreSelector selector) throws StoreException
{
String[] attrs = splitString(params.getAttributeAuthorityRevocationListAttribute());
String attrNames[] = splitString(params
.getLdapAttributeAuthorityRevocationListAttributeName());
String issuerAttributeNames[] = splitString(params
.getAttributeAuthorityRevocationListIssuerAttributeName());
List list = cRLIssuerSearch(selector, attrs, attrNames,
issuerAttributeNames);
Set resultSet = createCRLs(list, selector);
if (resultSet.size() == 0)
{
X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
list = cRLIssuerSearch(emptySelector, attrs, attrNames,
issuerAttributeNames);
resultSet.addAll(createCRLs(list, selector));
}
return resultSet;
}
/**
* Returns cross certificate pairs.
*
* @param selector The selector to use to find the cross certificates.
* @return A possible empty collection with {@link X509CertificatePair}s
* @throws StoreException
*/
public Collection getCrossCertificatePairs(
X509CertPairStoreSelector selector) throws StoreException
{
String[] attrs = splitString(params.getCrossCertificateAttribute());
String attrNames[] = splitString(params.getLdapCrossCertificateAttributeName());
String subjectAttributeNames[] = splitString(params
.getCrossCertificateSubjectAttributeName());
List list = crossCertificatePairSubjectSearch(selector, attrs,
attrNames, subjectAttributeNames);
Set resultSet = createCrossCertificatePairs(list, selector);
if (resultSet.size() == 0)
{
X509CertStoreSelector emptyCertselector = new X509CertStoreSelector();
X509CertPairStoreSelector emptySelector = new X509CertPairStoreSelector();
emptySelector.setForwardSelector(emptyCertselector);
emptySelector.setReverseSelector(emptyCertselector);
list = crossCertificatePairSubjectSearch(emptySelector, attrs,
attrNames, subjectAttributeNames);
resultSet.addAll(createCrossCertificatePairs(list, selector));
}
return resultSet;
}
/**
* Returns end certificates.
* <p>
* The attributeDescriptorCertificate is self signed by a source of
* authority and holds a description of the privilege and its delegation
* rules.
*
* @param selector The selector to find the certificates.
* @return A possible empty collection with certificates.
* @throws StoreException
*/
public Collection getUserCertificates(X509CertStoreSelector selector)
throws StoreException
{
String[] attrs = splitString(params.getUserCertificateAttribute());
String attrNames[] = splitString(params.getLdapUserCertificateAttributeName());
String subjectAttributeNames[] = splitString(params
.getUserCertificateSubjectAttributeName());
List list = certSubjectSerialSearch(selector, attrs, attrNames,
subjectAttributeNames);
Set resultSet = createCerts(list, selector);
if (resultSet.size() == 0)
{
X509CertStoreSelector emptySelector = new X509CertStoreSelector();
list = certSubjectSerialSearch(emptySelector, attrs, attrNames,
subjectAttributeNames);
resultSet.addAll(createCerts(list, selector));
}
return resultSet;
}
/**
* Returns attribute certificates for an attribute authority
* <p>
* The aAcertificate holds the privileges of an attribute authority.
* </p>
* @param selector The selector to find the attribute certificates.
* @return A possible empty collection with attribute certificates.
* @throws StoreException
*/
public Collection getAACertificates(X509AttributeCertStoreSelector selector)
throws StoreException
{
String[] attrs = splitString(params.getAACertificateAttribute());
String attrNames[] = splitString(params.getLdapAACertificateAttributeName());
String subjectAttributeNames[] = splitString(params.getAACertificateSubjectAttributeName());
List list = attrCertSubjectSerialSearch(selector, attrs, attrNames,
subjectAttributeNames);
Set resultSet = createAttributeCertificates(list, selector);
if (resultSet.size() == 0)
{
X509AttributeCertStoreSelector emptySelector = new X509AttributeCertStoreSelector();
list = attrCertSubjectSerialSearch(emptySelector, attrs, attrNames,
subjectAttributeNames);
resultSet.addAll(createAttributeCertificates(list, selector));
}
return resultSet;
}
/**
* Returns an attribute certificate for an authority
* <p>
* The attributeDescriptorCertificate is self signed by a source of
* authority and holds a description of the privilege and its delegation
* rules.
* </p>
* @param selector The selector to find the attribute certificates.
* @return A possible empty collection with attribute certificates.
* @throws StoreException
*/
public Collection getAttributeDescriptorCertificates(
X509AttributeCertStoreSelector selector) throws StoreException
{
String[] attrs = splitString(params.getAttributeDescriptorCertificateAttribute());
String attrNames[] = splitString(params
.getLdapAttributeDescriptorCertificateAttributeName());
String subjectAttributeNames[] = splitString(params
.getAttributeDescriptorCertificateSubjectAttributeName());
List list = attrCertSubjectSerialSearch(selector, attrs, attrNames,
subjectAttributeNames);
Set resultSet = createAttributeCertificates(list, selector);
if (resultSet.size() == 0)
{
X509AttributeCertStoreSelector emptySelector = new X509AttributeCertStoreSelector();
list = attrCertSubjectSerialSearch(emptySelector, attrs, attrNames,
subjectAttributeNames);
resultSet.addAll(createAttributeCertificates(list, selector));
}
return resultSet;
}
/**
* Returns CA certificates.
* <p>
* The cACertificate attribute of a CA's directory entry shall be used to
* store self-issued certificates (if any) and certificates issued to this
* CA by CAs in the same realm as this CA.
* </p>
* @param selector The selector to find the certificates.
* @return A possible empty collection with certificates.
* @throws StoreException
*/
public Collection getCACertificates(X509CertStoreSelector selector)
throws StoreException
{
String[] attrs = splitString(params.getCACertificateAttribute());
String attrNames[] = splitString(params.getLdapCACertificateAttributeName());
String subjectAttributeNames[] = splitString(params
.getCACertificateSubjectAttributeName());
List list = certSubjectSerialSearch(selector, attrs, attrNames,
subjectAttributeNames);
Set resultSet = createCerts(list, selector);
if (resultSet.size() == 0)
{
X509CertStoreSelector emptySelector = new X509CertStoreSelector();
list = certSubjectSerialSearch(emptySelector, attrs, attrNames,
subjectAttributeNames);
resultSet.addAll(createCerts(list, selector));
}
return resultSet;
}
/**
* Returns the delta revocation list for revoked certificates.
*
* @param selector The CRL selector to use to find the CRLs.
* @return A possible empty collection with CRLs.
* @throws StoreException
*/
public Collection getDeltaCertificateRevocationLists(
X509CRLStoreSelector selector) throws StoreException
{
String[] attrs = splitString(params.getDeltaRevocationListAttribute());
String attrNames[] = splitString(params.getLdapDeltaRevocationListAttributeName());
String issuerAttributeNames[] = splitString(params
.getDeltaRevocationListIssuerAttributeName());
List list = cRLIssuerSearch(selector, attrs, attrNames,
issuerAttributeNames);
Set resultSet = createCRLs(list, selector);
if (resultSet.size() == 0)
{
X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
list = cRLIssuerSearch(emptySelector, attrs, attrNames,
issuerAttributeNames);
resultSet.addAll(createCRLs(list, selector));
}
return resultSet;
}
/**
* Returns an attribute certificate for an user.
* <p>
* The attributeCertificateAttribute holds the privileges of a user
* </p>
* @param selector The selector to find the attribute certificates.
* @return A possible empty collection with attribute certificates.
* @throws StoreException
*/
public Collection getAttributeCertificateAttributes(
X509AttributeCertStoreSelector selector) throws StoreException
{
String[] attrs = splitString(params.getAttributeCertificateAttributeAttribute());
String attrNames[] = splitString(params
.getLdapAttributeCertificateAttributeAttributeName());
String subjectAttributeNames[] = splitString(params
.getAttributeCertificateAttributeSubjectAttributeName());
List list = attrCertSubjectSerialSearch(selector, attrs, attrNames,
subjectAttributeNames);
Set resultSet = createAttributeCertificates(list, selector);
if (resultSet.size() == 0)
{
X509AttributeCertStoreSelector emptySelector = new X509AttributeCertStoreSelector();
list = attrCertSubjectSerialSearch(emptySelector, attrs, attrNames,
subjectAttributeNames);
resultSet.addAll(createAttributeCertificates(list, selector));
}
return resultSet;
}
/**
* Returns the certificate revocation lists for revoked certificates.
*
* @param selector The CRL selector to use to find the CRLs.
* @return A possible empty collection with CRLs.
* @throws StoreException
*/
public Collection getCertificateRevocationLists(
X509CRLStoreSelector selector) throws StoreException
{
String[] attrs = splitString(params.getCertificateRevocationListAttribute());
String attrNames[] = splitString(params
.getLdapCertificateRevocationListAttributeName());
String issuerAttributeNames[] = splitString(params
.getCertificateRevocationListIssuerAttributeName());
List list = cRLIssuerSearch(selector, attrs, attrNames,
issuerAttributeNames);
Set resultSet = createCRLs(list, selector);
if (resultSet.size() == 0)
{
X509CRLStoreSelector emptySelector = new X509CRLStoreSelector();
list = cRLIssuerSearch(emptySelector, attrs, attrNames,
issuerAttributeNames);
resultSet.addAll(createCRLs(list, selector));
}
return resultSet;
}
private Map cacheMap = new HashMap(cacheSize);
private static int cacheSize = 32;
private static long lifeTime = 60 * 1000;
private synchronized void addToCache(String searchCriteria, List list)
{
Date now = new Date(System.currentTimeMillis());
List cacheEntry = new ArrayList();
cacheEntry.add(now);
cacheEntry.add(list);
if (cacheMap.containsKey(searchCriteria))
{
cacheMap.put(searchCriteria, cacheEntry);
}
else
{
if (cacheMap.size() >= cacheSize)
{
// replace oldest
Iterator it = cacheMap.entrySet().iterator();
long oldest = now.getTime();
Object replace = null;
while (it.hasNext())
{
Map.Entry entry = (Map.Entry)it.next();
long current = ((Date)((List)entry.getValue()).get(0))
.getTime();
if (current < oldest)
{
oldest = current;
replace = entry.getKey();
}
}
cacheMap.remove(replace);
}
cacheMap.put(searchCriteria, cacheEntry);
}
}
private List getFromCache(String searchCriteria)
{
List entry = (List)cacheMap.get(searchCriteria);
long now = System.currentTimeMillis();
if (entry != null)
{
// too old
if (((Date)entry.get(0)).getTime() < (now - lifeTime))
{
return null;
}
return (List)entry.get(1);
}
return null;
}
/*
* spilt string based on spaces
*/
private String[] splitString(String str)
{
return str.split("\\s+");
}
private String getSubjectAsString(X509CertStoreSelector xselector)
{
try
{
byte[] encSubject = xselector.getSubjectAsBytes();
if (encSubject != null)
{
return new X500Principal(encSubject).getName("RFC1779");
}
}
catch (IOException e)
{
throw new StoreException("exception processing name: " + e.getMessage(), e);
}
return null;
}
private X500Principal getCertificateIssuer(X509Certificate cert)
{
return cert.getIssuerX500Principal();
}
}