diff options
author | Roberto Tyley <roberto.tyley@gmail.com> | 2014-07-15 01:38:01 +0400 |
---|---|---|
committer | Roberto Tyley <roberto.tyley@gmail.com> | 2014-07-26 11:23:17 +0400 |
commit | 7cb752aaf746dc0b473afeb9e892b7fbc12666c5 (patch) | |
tree | cc4f91ddc18332b5adbe82e3fcb040d976c90105 /prov/src/main/jdk1.4/org/spongycastle/x509 | |
parent | 551830f8ea5177042af2c7dd1fc90888bc67387d (diff) |
Execute become-spongy.sh
https://github.com/rtyley/spongycastle/blob/3040af/become-spongy.sh
Diffstat (limited to 'prov/src/main/jdk1.4/org/spongycastle/x509')
3 files changed, 1534 insertions, 0 deletions
diff --git a/prov/src/main/jdk1.4/org/spongycastle/x509/X509CRLStoreSelector.java b/prov/src/main/jdk1.4/org/spongycastle/x509/X509CRLStoreSelector.java new file mode 100644 index 00000000..4748bfc5 --- /dev/null +++ b/prov/src/main/jdk1.4/org/spongycastle/x509/X509CRLStoreSelector.java @@ -0,0 +1,330 @@ +package org.spongycastle.x509; + +import org.spongycastle.asn1.ASN1Integer; +import org.spongycastle.asn1.x509.X509Extensions; +import org.spongycastle.util.Arrays; +import org.spongycastle.util.Selector; +import org.spongycastle.x509.extension.X509ExtensionUtil; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.cert.CRL; +import java.security.cert.X509CRL; +import java.security.cert.X509CRLSelector; + +/** + * This class is a Selector implementation for X.509 certificate revocation + * lists. + * + * @see org.spongycastle.util.Selector + * @see org.spongycastle.x509.X509Store + * @see org.spongycastle.jce.provider.X509StoreCRLCollection + */ +public class X509CRLStoreSelector + extends X509CRLSelector + implements Selector +{ + private boolean deltaCRLIndicator = false; + + private boolean completeCRLEnabled = false; + + private BigInteger maxBaseCRLNumber = null; + + private byte[] issuingDistributionPoint = null; + + private boolean issuingDistributionPointEnabled = false; + + private X509AttributeCertificate attrCertChecking; + + /** + * Returns if the issuing distribution point criteria should be applied. + * Defaults to <code>false</code>. + * <p> + * You may also set the issuing distribution point criteria if not a missing + * issuing distribution point should be assumed. + * + * @return Returns if the issuing distribution point check is enabled. + */ + public boolean isIssuingDistributionPointEnabled() + { + return issuingDistributionPointEnabled; + } + + /** + * Enables or disables the issuing distribution point check. + * + * @param issuingDistributionPointEnabled <code>true</code> to enable the + * issuing distribution point check. + */ + public void setIssuingDistributionPointEnabled( + boolean issuingDistributionPointEnabled) + { + this.issuingDistributionPointEnabled = issuingDistributionPointEnabled; + } + + /** + * Sets the attribute certificate being checked. This is not a criterion. + * Rather, it is optional information that may help a {@link X509Store} find + * CRLs that would be relevant when checking revocation for the specified + * attribute certificate. If <code>null</code> is specified, then no such + * optional information is provided. + * + * @param attrCert the <code>X509AttributeCertificate</code> being checked (or + * <code>null</code>) + * @see #getAttrCertificateChecking() + */ + public void setAttrCertificateChecking(X509AttributeCertificate attrCert) + { + attrCertChecking = attrCert; + } + + /** + * Returns the attribute certificate being checked. + * + * @return Returns the attribute certificate being checked. + * @see #setAttrCertificateChecking(X509AttributeCertificate) + */ + public X509AttributeCertificate getAttrCertificateChecking() + { + return attrCertChecking; + } + + public boolean match(Object obj) + { + if (!(obj instanceof X509CRL)) + { + return false; + } + X509CRL crl = (X509CRL)obj; + ASN1Integer dci = null; + try + { + byte[] bytes = crl + .getExtensionValue(X509Extensions.DeltaCRLIndicator.getId()); + if (bytes != null) + { + dci = ASN1Integer.getInstance(X509ExtensionUtil + .fromExtensionValue(bytes)); + } + } + catch (Exception e) + { + return false; + } + if (isDeltaCRLIndicatorEnabled()) + { + if (dci == null) + { + return false; + } + } + if (isCompleteCRLEnabled()) + { + if (dci != null) + { + return false; + } + } + if (dci != null) + { + + if (maxBaseCRLNumber != null) + { + if (dci.getPositiveValue().compareTo(maxBaseCRLNumber) == 1) + { + return false; + } + } + } + if (issuingDistributionPointEnabled) + { + byte[] idp = crl + .getExtensionValue(X509Extensions.IssuingDistributionPoint + .getId()); + if (issuingDistributionPoint == null) + { + if (idp != null) + { + return false; + } + } + else + { + if (!Arrays.areEqual(idp, issuingDistributionPoint)) + { + return false; + } + } + + } + return super.match((X509CRL)obj); + } + + public boolean match(CRL crl) + { + return match((Object)crl); + } + + /** + * Returns if this selector must match CRLs with the delta CRL indicator + * extension set. Defaults to <code>false</code>. + * + * @return Returns <code>true</code> if only CRLs with the delta CRL + * indicator extension are selected. + */ + public boolean isDeltaCRLIndicatorEnabled() + { + return deltaCRLIndicator; + } + + /** + * If this is set to <code>true</code> the CRL reported contains the delta + * CRL indicator CRL extension. + * <p> + * {@link #setCompleteCRLEnabled(boolean)} and + * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. + * + * @param deltaCRLIndicator <code>true</code> if the delta CRL indicator + * extension must be in the CRL. + */ + public void setDeltaCRLIndicatorEnabled(boolean deltaCRLIndicator) + { + this.deltaCRLIndicator = deltaCRLIndicator; + } + + /** + * Returns an instance of this from a <code>X509CRLSelector</code>. + * + * @param selector A <code>X509CRLSelector</code> instance. + * @return An instance of an <code>X509CRLStoreSelector</code>. + * @exception IllegalArgumentException if selector is null or creation + * fails. + */ + public static X509CRLStoreSelector getInstance(X509CRLSelector selector) + { + if (selector == null) + { + throw new IllegalArgumentException( + "cannot create from null selector"); + } + X509CRLStoreSelector cs = new X509CRLStoreSelector(); + cs.setCertificateChecking(selector.getCertificateChecking()); + cs.setDateAndTime(selector.getDateAndTime()); + try + { + cs.setIssuerNames(selector.getIssuerNames()); + } + catch (IOException e) + { + // cannot happen + throw new IllegalArgumentException(e.getMessage()); + } + //cs.setIssuers(selector.getIssuers()); + cs.setMaxCRLNumber(selector.getMaxCRL()); + cs.setMinCRLNumber(selector.getMinCRL()); + return cs; + } + + public Object clone() + { + X509CRLStoreSelector sel = X509CRLStoreSelector.getInstance(this); + sel.deltaCRLIndicator = deltaCRLIndicator; + sel.completeCRLEnabled = completeCRLEnabled; + sel.maxBaseCRLNumber = maxBaseCRLNumber; + sel.attrCertChecking = attrCertChecking; + sel.issuingDistributionPointEnabled = issuingDistributionPointEnabled; + sel.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); + return sel; + } + + /** + * If <code>true</code> only complete CRLs are returned. Defaults to + * <code>false</code>. + * + * @return <code>true</code> if only complete CRLs are returned. + */ + public boolean isCompleteCRLEnabled() + { + return completeCRLEnabled; + } + + /** + * If set to <code>true</code> only complete CRLs are returned. + * <p> + * {@link #setCompleteCRLEnabled(boolean)} and + * {@link #setDeltaCRLIndicatorEnabled(boolean)} excluded each other. + * + * @param completeCRLEnabled <code>true</code> if only complete CRLs + * should be returned. + */ + public void setCompleteCRLEnabled(boolean completeCRLEnabled) + { + this.completeCRLEnabled = completeCRLEnabled; + } + + /** + * Get the maximum base CRL number. Defaults to <code>null</code>. + * + * @return Returns the maximum base CRL number. + * @see #setMaxBaseCRLNumber(BigInteger) + */ + public BigInteger getMaxBaseCRLNumber() + { + return maxBaseCRLNumber; + } + + /** + * Sets the maximum base CRL number. Setting to <code>null</code> disables + * this cheack. + * <p> + * This is only meaningful for delta CRLs. Complete CRLs must have a CRL + * number which is greater or equal than the base number of the + * corresponding CRL. + * + * @param maxBaseCRLNumber The maximum base CRL number to set. + */ + public void setMaxBaseCRLNumber(BigInteger maxBaseCRLNumber) + { + this.maxBaseCRLNumber = maxBaseCRLNumber; + } + + /** + * Returns the issuing distribution point. Defaults to <code>null</code>, + * which is a missing issuing distribution point extension. + * <p> + * The internal byte array is cloned before it is returned. + * <p> + * The criteria must be enable with + * {@link #setIssuingDistributionPointEnabled(boolean)}. + * + * @return Returns the issuing distribution point. + * @see #setIssuingDistributionPoint(byte[]) + */ + public byte[] getIssuingDistributionPoint() + { + return Arrays.clone(issuingDistributionPoint); + } + + /** + * Sets the issuing distribution point. + * <p> + * The issuing distribution point extension is a CRL extension which + * identifies the scope and the distribution point of a CRL. The scope + * contains among others information about revocation reasons contained in + * the CRL. Delta CRLs and complete CRLs must have matching issuing + * distribution points. + * <p> + * The byte array is cloned to protect against subsequent modifications. + * <p> + * You must also enable or disable this criteria with + * {@link #setIssuingDistributionPointEnabled(boolean)}. + * + * @param issuingDistributionPoint The issuing distribution point to set. + * This is the DER encoded OCTET STRING extension value. + * @see #getIssuingDistributionPoint() + */ + public void setIssuingDistributionPoint(byte[] issuingDistributionPoint) + { + this.issuingDistributionPoint = Arrays.clone(issuingDistributionPoint); + } +} diff --git a/prov/src/main/jdk1.4/org/spongycastle/x509/X509CertStoreSelector.java b/prov/src/main/jdk1.4/org/spongycastle/x509/X509CertStoreSelector.java new file mode 100644 index 00000000..61664c44 --- /dev/null +++ b/prov/src/main/jdk1.4/org/spongycastle/x509/X509CertStoreSelector.java @@ -0,0 +1,86 @@ +package org.spongycastle.x509; + +import org.spongycastle.util.Selector; + +import java.io.IOException; +import java.security.cert.Certificate; +import java.security.cert.X509CertSelector; +import java.security.cert.X509Certificate; + +/** + * This class is a Selector implementation for X.509 certificates. + * + * @see org.spongycastle.util.Selector + * @see org.spongycastle.x509.X509Store + * @see org.spongycastle.jce.provider.X509StoreCertCollection + */ +public class X509CertStoreSelector + extends X509CertSelector + implements Selector +{ + public boolean match(Object obj) + { + if (!(obj instanceof X509Certificate)) + { + return false; + } + + X509Certificate other = (X509Certificate)obj; + + return super.match(other); + } + + public boolean match(Certificate cert) + { + return match((Object)cert); + } + + public Object clone() + { + X509CertStoreSelector selector = (X509CertStoreSelector)super.clone(); + + return selector; + } + + /** + * Returns an instance of this from a <code>X509CertSelector</code>. + * + * @param selector A <code>X509CertSelector</code> instance. + * @return An instance of an <code>X509CertStoreSelector</code>. + * @exception IllegalArgumentException if selector is null or creation fails. + */ + public static X509CertStoreSelector getInstance(X509CertSelector selector) + { + if (selector == null) + { + throw new IllegalArgumentException("cannot create from null selector"); + } + X509CertStoreSelector cs = new X509CertStoreSelector(); + cs.setAuthorityKeyIdentifier(selector.getAuthorityKeyIdentifier()); + cs.setBasicConstraints(selector.getBasicConstraints()); + cs.setCertificate(selector.getCertificate()); + cs.setCertificateValid(selector.getCertificateValid()); + cs.setMatchAllSubjectAltNames(selector.getMatchAllSubjectAltNames()); + try + { + cs.setPathToNames(selector.getPathToNames()); + cs.setExtendedKeyUsage(selector.getExtendedKeyUsage()); + cs.setNameConstraints(selector.getNameConstraints()); + cs.setPolicy(selector.getPolicy()); + cs.setSubjectPublicKeyAlgID(selector.getSubjectPublicKeyAlgID()); + cs.setIssuer(selector.getIssuerAsBytes()); + cs.setSubject(selector.getSubjectAsBytes()); + } + catch (IOException e) + { + throw new IllegalArgumentException("error in passed in selector: " + e); + } + cs.setKeyUsage(selector.getKeyUsage()); + cs.setPrivateKeyValid(selector.getPrivateKeyValid()); + cs.setSerialNumber(selector.getSerialNumber()); + cs.setSubjectKeyIdentifier(selector.getSubjectKeyIdentifier()); + cs.setSubjectPublicKey(selector.getSubjectPublicKey()); + return cs; + } + +} diff --git a/prov/src/main/jdk1.4/org/spongycastle/x509/util/LDAPStoreHelper.java b/prov/src/main/jdk1.4/org/spongycastle/x509/util/LDAPStoreHelper.java new file mode 100644 index 00000000..b78c4a76 --- /dev/null +++ b/prov/src/main/jdk1.4/org/spongycastle/x509/util/LDAPStoreHelper.java @@ -0,0 +1,1118 @@ +package org.spongycastle.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.spongycastle.asn1.ASN1InputStream; +import org.spongycastle.asn1.x509.Certificate; +import org.spongycastle.asn1.x509.CertificatePair; +import org.spongycastle.jce.X509LDAPCertStoreParameters; +import org.spongycastle.jce.provider.X509AttrCertParser; +import org.spongycastle.jce.provider.X509CRLParser; +import org.spongycastle.jce.provider.X509CertPairParser; +import org.spongycastle.jce.provider.X509CertParser; +import org.spongycastle.util.StoreException; +import org.spongycastle.x509.X509AttributeCertStoreSelector; +import org.spongycastle.x509.X509AttributeCertificate; +import org.spongycastle.x509.X509CRLStoreSelector; +import org.spongycastle.x509.X509CertPairStoreSelector; +import org.spongycastle.x509.X509CertStoreSelector; +import org.spongycastle.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.spongycastle.jce.X509LDAPCertStoreParameters} with the given + * information of the subject (for all kind of certificates) or issuer (for + * CRLs), respectively, if a {@link org.spongycastle.x509.X509CertStoreSelector} or + * {@link org.spongycastle.x509.X509AttributeCertificate} is given with that + * details. + * <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.spongycastle.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. + * + * @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. + * + * @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. + * + * @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. + * + * @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. + * + * @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 + * + * @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(); + } +} |