/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.provider.certpath.ldap;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.*;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NameNotFoundException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttributes;

import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.*;
import javax.naming.CommunicationException;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.security.auth.x500.X500Principal;

import sun.security.util.HexDumpEncoder;
import sun.security.provider.certpath.X509CertificatePair;
import sun.security.util.Cache;
import sun.security.util.Debug;

/**
 * Core implementation of a LDAP Cert Store.
 * @see java.security.cert.CertStore
 *
 * @since       9
 */
final class LDAPCertStoreImpl {

    private static final Debug debug = Debug.getInstance("certpath");

    private final static boolean DEBUG = false;

    /**
     * LDAP attribute identifiers.
     */
    private static final String USER_CERT = "userCertificate;binary";
    private static final String CA_CERT = "cACertificate;binary";
    private static final String CROSS_CERT = "crossCertificatePair;binary";
    private static final String CRL = "certificateRevocationList;binary";
    private static final String ARL = "authorityRevocationList;binary";
    private static final String DELTA_CRL = "deltaRevocationList;binary";

    // Constants for various empty values
    private final static String[] STRING0 = new String[0];

    private final static byte[][] BB0 = new byte[0][];

    private final static Attributes EMPTY_ATTRIBUTES = new BasicAttributes();

    // cache related constants
    private final static int DEFAULT_CACHE_SIZE = 750;
    private final static int DEFAULT_CACHE_LIFETIME = 30;

    private final static int LIFETIME;

    private final static String PROP_LIFETIME =
                            "sun.security.certpath.ldap.cache.lifetime";

    /*
     * Internal system property, that when set to "true", disables the
     * JNDI application resource files lookup to prevent recursion issues
     * when validating signed JARs with LDAP URLs in certificates.
     */
    private final static String PROP_DISABLE_APP_RESOURCE_FILES =
        "sun.security.certpath.ldap.disable.app.resource.files";

    static {
        String s = AccessController.doPrivileged(
            (PrivilegedAction<String>) () -> System.getProperty(PROP_LIFETIME));
        if (s != null) {
            LIFETIME = Integer.parseInt(s); // throws NumberFormatException
        } else {
            LIFETIME = DEFAULT_CACHE_LIFETIME;
        }
    }

    /**
     * The CertificateFactory used to decode certificates from
     * their binary stored form.
     */
    private CertificateFactory cf;
    /**
     * The JNDI directory context.
     */
    private LdapContext ctx;

    /**
     * Flag indicating that communication error occurred.
     */
    private boolean communicationError = false;

    /**
     * Flag indicating whether we should prefetch CRLs.
     */
    private boolean prefetchCRLs = false;

    private final Cache<String, byte[][]> valueCache;

    private int cacheHits = 0;
    private int cacheMisses = 0;
    private int requests = 0;

    /**
     * Creates a <code>CertStore</code> with the specified parameters.
     */
    LDAPCertStoreImpl(String serverName, int port)
        throws InvalidAlgorithmParameterException {
        createInitialDirContext(serverName, port);
        // Create CertificateFactory for use later on
        try {
            cf = CertificateFactory.getInstance("X.509");
        } catch (CertificateException e) {
            throw new InvalidAlgorithmParameterException(
                "unable to create CertificateFactory for X.509");
        }
        if (LIFETIME == 0) {
            valueCache = Cache.newNullCache();
        } else if (LIFETIME < 0) {
            valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE);
        } else {
            valueCache = Cache.newSoftMemoryCache(DEFAULT_CACHE_SIZE, LIFETIME);
        }
    }

    /**
     * Create InitialDirContext.
     *
     * @param server Server DNS name hosting LDAP service
     * @param port   Port at which server listens for requests
     * @throws InvalidAlgorithmParameterException if creation fails
     */
    private void createInitialDirContext(String server, int port)
            throws InvalidAlgorithmParameterException {
        String url = "ldap://" + server + ":" + port;
        Hashtable<String,Object> env = new Hashtable<>();
        env.put(Context.INITIAL_CONTEXT_FACTORY,
                "com.sun.jndi.ldap.LdapCtxFactory");
        env.put(Context.PROVIDER_URL, url);

        // If property is set to true, disable application resource file lookup.
        boolean disableAppResourceFiles = AccessController.doPrivileged(
            (PrivilegedAction<Boolean>) () -> Boolean.getBoolean(PROP_DISABLE_APP_RESOURCE_FILES));
        if (disableAppResourceFiles) {
            if (debug != null) {
                debug.println("LDAPCertStore disabling app resource files");
            }
            env.put("com.sun.naming.disable.app.resource.files", "true");
        }

        try {
            ctx = new InitialLdapContext(env, null);
            /*
             * By default, follow referrals unless application has
             * overridden property in an application resource file.
             */
            Hashtable<?,?> currentEnv = ctx.getEnvironment();
            if (currentEnv.get(Context.REFERRAL) == null) {
                ctx.addToEnvironment(Context.REFERRAL, "follow");
            }
        } catch (NamingException e) {
            if (debug != null) {
                debug.println("LDAPCertStore.engineInit about to throw "
                    + "InvalidAlgorithmParameterException");
                e.printStackTrace();
            }
            Exception ee = new InvalidAlgorithmParameterException
                ("unable to create InitialDirContext using supplied parameters");
            ee.initCause(e);
            throw (InvalidAlgorithmParameterException)ee;
        }
    }

    /**
     * Private class encapsulating the actual LDAP operations and cache
     * handling. Use:
     *
     *   LDAPRequest request = new LDAPRequest(dn);
     *   request.addRequestedAttribute(CROSS_CERT);
     *   request.addRequestedAttribute(CA_CERT);
     *   byte[][] crossValues = request.getValues(CROSS_CERT);
     *   byte[][] caValues = request.getValues(CA_CERT);
     *
     * At most one LDAP request is sent for each instance created. If all
     * getValues() calls can be satisfied from the cache, no request
     * is sent at all. If a request is sent, all requested attributes
     * are always added to the cache irrespective of whether the getValues()
     * method is called.
     */
    private class LDAPRequest {

        private final String name;
        private Map<String, byte[][]> valueMap;
        private final List<String> requestedAttributes;

        LDAPRequest(String name) {
            this.name = name;
            requestedAttributes = new ArrayList<>(5);
        }

        String getName() {
            return name;
        }

        void addRequestedAttribute(String attrId) {
            if (valueMap != null) {
                throw new IllegalStateException("Request already sent");
            }
            requestedAttributes.add(attrId);
        }

        /**
         * Gets one or more binary values from an attribute.
         *
         * @param name          the location holding the attribute
         * @param attrId                the attribute identifier
         * @return                      an array of binary values (byte arrays)
         * @throws NamingException      if a naming exception occurs
         */
        byte[][] getValues(String attrId) throws NamingException {
            if (DEBUG && ((cacheHits + cacheMisses) % 50 == 0)) {
                System.out.println("Cache hits: " + cacheHits + "; misses: "
                        + cacheMisses);
            }
            String cacheKey = name + "|" + attrId;
            byte[][] values = valueCache.get(cacheKey);
            if (values != null) {
                cacheHits++;
                return values;
            }
            cacheMisses++;
            Map<String, byte[][]> attrs = getValueMap();
            values = attrs.get(attrId);
            return values;
        }

        /**
         * Get a map containing the values for this request. The first time
         * this method is called on an object, the LDAP request is sent,
         * the results parsed and added to a private map and also to the
         * cache of this LDAPCertStore. Subsequent calls return the private
         * map immediately.
         *
         * The map contains an entry for each requested attribute. The
         * attribute name is the key, values are byte[][]. If there are no
         * values for that attribute, values are byte[0][].
         *
         * @return                      the value Map
         * @throws NamingException      if a naming exception occurs
         */
        private Map<String, byte[][]> getValueMap() throws NamingException {
            if (valueMap != null) {
                return valueMap;
            }
            if (DEBUG) {
                System.out.println("Request: " + name + ":" + requestedAttributes);
                requests++;
                if (requests % 5 == 0) {
                    System.out.println("LDAP requests: " + requests);
                }
            }
            valueMap = new HashMap<>(8);
            String[] attrIds = requestedAttributes.toArray(STRING0);
            Attributes attrs;

            if (communicationError) {
                ctx.reconnect(null);
                communicationError = false;
            }

            try {
                attrs = ctx.getAttributes(name, attrIds);
            } catch (CommunicationException ce) {
                communicationError = true;
                throw ce;
            } catch (NameNotFoundException e) {
                // name does not exist on this LDAP server
                // treat same as not attributes found
                attrs = EMPTY_ATTRIBUTES;
            }
            for (String attrId : requestedAttributes) {
                Attribute attr = attrs.get(attrId);
                byte[][] values = getAttributeValues(attr);
                cacheAttribute(attrId, values);
                valueMap.put(attrId, values);
            }
            return valueMap;
        }

        /**
         * Add the values to the cache.
         */
        private void cacheAttribute(String attrId, byte[][] values) {
            String cacheKey = name + "|" + attrId;
            valueCache.put(cacheKey, values);
        }

        /**
         * Get the values for the given attribute. If the attribute is null
         * or does not contain any values, a zero length byte array is
         * returned. NOTE that it is assumed that all values are byte arrays.
         */
        private byte[][] getAttributeValues(Attribute attr)
                throws NamingException {
            byte[][] values;
            if (attr == null) {
                values = BB0;
            } else {
                values = new byte[attr.size()][];
                int i = 0;
                NamingEnumeration<?> enum_ = attr.getAll();
                while (enum_.hasMore()) {
                    Object obj = enum_.next();
                    if (debug != null) {
                        if (obj instanceof String) {
                            debug.println("LDAPCertStore.getAttrValues() "
                                + "enum.next is a string!: " + obj);
                        }
                    }
                    byte[] value = (byte[])obj;
                    values[i++] = value;
                }
            }
            return values;
        }

    }

    /*
     * Gets certificates from an attribute id and location in the LDAP
     * directory. Returns a Collection containing only the Certificates that
     * match the specified CertSelector.
     *
     * @param name the location holding the attribute
     * @param id the attribute identifier
     * @param sel a CertSelector that the Certificates must match
     * @return a Collection of Certificates found
     * @throws CertStoreException       if an exception occurs
     */
    private Collection<X509Certificate> getCertificates(LDAPRequest request,
        String id, X509CertSelector sel) throws CertStoreException {

        /* fetch encoded certs from storage */
        byte[][] encodedCert;
        try {
            encodedCert = request.getValues(id);
        } catch (NamingException namingEx) {
            throw new CertStoreException(namingEx);
        }

        int n = encodedCert.length;
        if (n == 0) {
            return Collections.emptySet();
        }

        List<X509Certificate> certs = new ArrayList<>(n);
        /* decode certs and check if they satisfy selector */
        for (int i = 0; i < n; i++) {
            ByteArrayInputStream bais = new ByteArrayInputStream(encodedCert[i]);
            try {
                Certificate cert = cf.generateCertificate(bais);
                if (sel.match(cert)) {
                  certs.add((X509Certificate)cert);
                }
            } catch (CertificateException e) {
                if (debug != null) {
                    debug.println("LDAPCertStore.getCertificates() encountered "
                        + "exception while parsing cert, skipping the bad data: ");
                    HexDumpEncoder encoder = new HexDumpEncoder();
                    debug.println(
                        "[ " + encoder.encodeBuffer(encodedCert[i]) + " ]");
                }
            }
        }

        return certs;
    }

    /*
     * Gets certificate pairs from an attribute id and location in the LDAP
     * directory.
     *
     * @param name the location holding the attribute
     * @param id the attribute identifier
     * @return a Collection of X509CertificatePairs found
     * @throws CertStoreException       if an exception occurs
     */
    private Collection<X509CertificatePair> getCertPairs(
        LDAPRequest request, String id) throws CertStoreException {

        /* fetch the encoded cert pairs from storage */
        byte[][] encodedCertPair;
        try {
            encodedCertPair = request.getValues(id);
        } catch (NamingException namingEx) {
            throw new CertStoreException(namingEx);
        }

        int n = encodedCertPair.length;
        if (n == 0) {
            return Collections.emptySet();
        }

        List<X509CertificatePair> certPairs = new ArrayList<>(n);
        /* decode each cert pair and add it to the Collection */
        for (int i = 0; i < n; i++) {
            try {
                X509CertificatePair certPair =
                    X509CertificatePair.generateCertificatePair(encodedCertPair[i]);
                certPairs.add(certPair);
            } catch (CertificateException e) {
                if (debug != null) {
                    debug.println(
                        "LDAPCertStore.getCertPairs() encountered exception "
                        + "while parsing cert, skipping the bad data: ");
                    HexDumpEncoder encoder = new HexDumpEncoder();
                    debug.println(
                        "[ " + encoder.encodeBuffer(encodedCertPair[i]) + " ]");
                }
            }
        }

        return certPairs;
    }

    /*
     * Looks at certificate pairs stored in the crossCertificatePair attribute
     * at the specified location in the LDAP directory. Returns a Collection
     * containing all X509Certificates stored in the forward component that match
     * the forward X509CertSelector and all Certificates stored in the reverse
     * component that match the reverse X509CertSelector.
     * <p>
     * If either forward or reverse is null, all certificates from the
     * corresponding component will be rejected.
     *
     * @param name the location to look in
     * @param forward the forward X509CertSelector (or null)
     * @param reverse the reverse X509CertSelector (or null)
     * @return a Collection of X509Certificates found
     * @throws CertStoreException       if an exception occurs
     */
    private Collection<X509Certificate> getMatchingCrossCerts(
            LDAPRequest request, X509CertSelector forward,
            X509CertSelector reverse)
            throws CertStoreException {
        // Get the cert pairs
        Collection<X509CertificatePair> certPairs =
                                getCertPairs(request, CROSS_CERT);

        // Find Certificates that match and put them in a list
        ArrayList<X509Certificate> matchingCerts = new ArrayList<>();
        for (X509CertificatePair certPair : certPairs) {
            X509Certificate cert;
            if (forward != null) {
                cert = certPair.getForward();
                if ((cert != null) && forward.match(cert)) {
                    matchingCerts.add(cert);
                }
            }
            if (reverse != null) {
                cert = certPair.getReverse();
                if ((cert != null) && reverse.match(cert)) {
                    matchingCerts.add(cert);
                }
            }
        }
        return matchingCerts;
    }

    /**
     * Returns a <code>Collection</code> of <code>X509Certificate</code>s that
     * match the specified selector. If no <code>X509Certificate</code>s
     * match the selector, an empty <code>Collection</code> will be returned.
     * <p>
     * It is not practical to search every entry in the LDAP database for
     * matching <code>X509Certificate</code>s. Instead, the
     * <code>X509CertSelector</code> is examined in order to determine where
     * matching <code>Certificate</code>s are likely to be found (according
     * to the PKIX LDAPv2 schema, RFC 2587).
     * If the subject is specified, its directory entry is searched. If the
     * issuer is specified, its directory entry is searched. If neither the
     * subject nor the issuer are specified (or the selector is not an
     * <code>X509CertSelector</code>), a <code>CertStoreException</code> is
     * thrown.
     *
     * @param selector a <code>X509CertSelector</code> used to select which
     *  <code>Certificate</code>s should be returned.
     * @return a <code>Collection</code> of <code>X509Certificate</code>s that
     *         match the specified selector
     * @throws CertStoreException if an exception occurs
     */
    synchronized Collection<X509Certificate> getCertificates
        (X509CertSelector xsel, String ldapDN) throws CertStoreException {

        if (ldapDN == null) {
            ldapDN = xsel.getSubjectAsString();
        }
        int basicConstraints = xsel.getBasicConstraints();
        String issuer = xsel.getIssuerAsString();
        HashSet<X509Certificate> certs = new HashSet<>();
        if (debug != null) {
            debug.println("LDAPCertStore.engineGetCertificates() basicConstraints: "
                + basicConstraints);
        }

        // basicConstraints:
        // -2: only EE certs accepted
        // -1: no check is done
        //  0: any CA certificate accepted
        // >1: certificate's basicConstraints extension pathlen must match
        if (ldapDN != null) {
            if (debug != null) {
                debug.println("LDAPCertStore.engineGetCertificates() "
                    + " subject is not null");
            }
            LDAPRequest request = new LDAPRequest(ldapDN);
            if (basicConstraints > -2) {
                request.addRequestedAttribute(CROSS_CERT);
                request.addRequestedAttribute(CA_CERT);
                request.addRequestedAttribute(ARL);
                if (prefetchCRLs) {
                    request.addRequestedAttribute(CRL);
                }
            }
            if (basicConstraints < 0) {
                request.addRequestedAttribute(USER_CERT);
            }

            if (basicConstraints > -2) {
                certs.addAll(getMatchingCrossCerts(request, xsel, null));
                if (debug != null) {
                    debug.println("LDAPCertStore.engineGetCertificates() after "
                        + "getMatchingCrossCerts(subject,xsel,null),certs.size(): "
                        + certs.size());
                }
                certs.addAll(getCertificates(request, CA_CERT, xsel));
                if (debug != null) {
                    debug.println("LDAPCertStore.engineGetCertificates() after "
                        + "getCertificates(subject,CA_CERT,xsel),certs.size(): "
                        + certs.size());
                }
            }
            if (basicConstraints < 0) {
                certs.addAll(getCertificates(request, USER_CERT, xsel));
                if (debug != null) {
                    debug.println("LDAPCertStore.engineGetCertificates() after "
                        + "getCertificates(subject,USER_CERT, xsel),certs.size(): "
                        + certs.size());
                }
            }
        } else {
            if (debug != null) {
                debug.println
                    ("LDAPCertStore.engineGetCertificates() subject is null");
            }
            if (basicConstraints == -2) {
                throw new CertStoreException("need subject to find EE certs");
            }
            if (issuer == null) {
                throw new CertStoreException("need subject or issuer to find certs");
            }
        }
        if (debug != null) {
            debug.println("LDAPCertStore.engineGetCertificates() about to "
                + "getMatchingCrossCerts...");
        }
        if ((issuer != null) && (basicConstraints > -2)) {
            LDAPRequest request = new LDAPRequest(issuer);
            request.addRequestedAttribute(CROSS_CERT);
            request.addRequestedAttribute(CA_CERT);
            request.addRequestedAttribute(ARL);
            if (prefetchCRLs) {
                request.addRequestedAttribute(CRL);
            }

            certs.addAll(getMatchingCrossCerts(request, null, xsel));
            if (debug != null) {
                debug.println("LDAPCertStore.engineGetCertificates() after "
                    + "getMatchingCrossCerts(issuer,null,xsel),certs.size(): "
                    + certs.size());
            }
            certs.addAll(getCertificates(request, CA_CERT, xsel));
            if (debug != null) {
                debug.println("LDAPCertStore.engineGetCertificates() after "
                    + "getCertificates(issuer,CA_CERT,xsel),certs.size(): "
                    + certs.size());
            }
        }
        if (debug != null) {
            debug.println("LDAPCertStore.engineGetCertificates() returning certs");
        }
        return certs;
    }

    /*
     * Gets CRLs from an attribute id and location in the LDAP directory.
     * Returns a Collection containing only the CRLs that match the
     * specified X509CRLSelector.
     *
     * @param name the location holding the attribute
     * @param id the attribute identifier
     * @param sel a X509CRLSelector that the CRLs must match
     * @return a Collection of CRLs found
     * @throws CertStoreException       if an exception occurs
     */
    private Collection<X509CRL> getCRLs(LDAPRequest request, String id,
            X509CRLSelector sel) throws CertStoreException {

        /* fetch the encoded crls from storage */
        byte[][] encodedCRL;
        try {
            encodedCRL = request.getValues(id);
        } catch (NamingException namingEx) {
            throw new CertStoreException(namingEx);
        }

        int n = encodedCRL.length;
        if (n == 0) {
            return Collections.emptySet();
        }

        List<X509CRL> crls = new ArrayList<>(n);
        /* decode each crl and check if it matches selector */
        for (int i = 0; i < n; i++) {
            try {
                CRL crl = cf.generateCRL(new ByteArrayInputStream(encodedCRL[i]));
                if (sel.match(crl)) {
                    crls.add((X509CRL)crl);
                }
            } catch (CRLException e) {
                if (debug != null) {
                    debug.println("LDAPCertStore.getCRLs() encountered exception"
                        + " while parsing CRL, skipping the bad data: ");
                    HexDumpEncoder encoder = new HexDumpEncoder();
                    debug.println("[ " + encoder.encodeBuffer(encodedCRL[i]) + " ]");
                }
            }
        }

        return crls;
    }

    /**
     * Returns a <code>Collection</code> of <code>X509CRL</code>s that
     * match the specified selector. If no <code>X509CRL</code>s
     * match the selector, an empty <code>Collection</code> will be returned.
     * <p>
     * It is not practical to search every entry in the LDAP database for
     * matching <code>X509CRL</code>s. Instead, the <code>X509CRLSelector</code>
     * is examined in order to determine where matching <code>X509CRL</code>s
     * are likely to be found (according to the PKIX LDAPv2 schema, RFC 2587).
     * If issuerNames or certChecking are specified, the issuer's directory
     * entry is searched. If neither issuerNames or certChecking are specified
     * (or the selector is not an <code>X509CRLSelector</code>), a
     * <code>CertStoreException</code> is thrown.
     *
     * @param selector A <code>X509CRLSelector</code> used to select which
     *  <code>CRL</code>s should be returned. Specify <code>null</code>
     *  to return all <code>CRL</code>s.
     * @return A <code>Collection</code> of <code>X509CRL</code>s that
     *         match the specified selector
     * @throws CertStoreException if an exception occurs
     */
    synchronized Collection<X509CRL> getCRLs(X509CRLSelector xsel,
         String ldapDN) throws CertStoreException {

        HashSet<X509CRL> crls = new HashSet<>();

        // Look in directory entry for issuer of cert we're checking.
        Collection<Object> issuerNames;
        X509Certificate certChecking = xsel.getCertificateChecking();
        if (certChecking != null) {
            issuerNames = new HashSet<>();
            X500Principal issuer = certChecking.getIssuerX500Principal();
            issuerNames.add(issuer.getName(X500Principal.RFC2253));
        } else {
            // But if we don't know which cert we're checking, try the directory
            // entries of all acceptable CRL issuers
            if (ldapDN != null) {
                issuerNames = new HashSet<>();
                issuerNames.add(ldapDN);
            } else {
                issuerNames = xsel.getIssuerNames();
                if (issuerNames == null) {
                    throw new CertStoreException("need issuerNames or"
                       + " certChecking to find CRLs");
                }
            }
        }
        for (Object nameObject : issuerNames) {
            String issuerName;
            if (nameObject instanceof byte[]) {
                try {
                    X500Principal issuer = new X500Principal((byte[])nameObject);
                    issuerName = issuer.getName(X500Principal.RFC2253);
                } catch (IllegalArgumentException e) {
                    continue;
                }
            } else {
                issuerName = (String)nameObject;
            }
            // If all we want is CA certs, try to get the (probably shorter) ARL
            Collection<X509CRL> entryCRLs = Collections.emptySet();
            if (certChecking == null || certChecking.getBasicConstraints() != -1) {
                LDAPRequest request = new LDAPRequest(issuerName);
                request.addRequestedAttribute(CROSS_CERT);
                request.addRequestedAttribute(CA_CERT);
                request.addRequestedAttribute(ARL);
                if (prefetchCRLs) {
                    request.addRequestedAttribute(CRL);
                }
                try {
                    entryCRLs = getCRLs(request, ARL, xsel);
                    if (entryCRLs.isEmpty()) {
                        // no ARLs found. We assume that means that there are
                        // no ARLs on this server at all and prefetch the CRLs.
                        prefetchCRLs = true;
                    } else {
                        crls.addAll(entryCRLs);
                    }
                } catch (CertStoreException e) {
                    if (debug != null) {
                        debug.println("LDAPCertStore.engineGetCRLs non-fatal error "
                            + "retrieving ARLs:" + e);
                        e.printStackTrace();
                    }
                }
            }
            // Otherwise, get the CRL
            // if certChecking is null, we don't know if we should look in ARL or CRL
            // attribute, so check both for matching CRLs.
            if (entryCRLs.isEmpty() || certChecking == null) {
                LDAPRequest request = new LDAPRequest(issuerName);
                request.addRequestedAttribute(CRL);
                entryCRLs = getCRLs(request, CRL, xsel);
                crls.addAll(entryCRLs);
            }
        }
        return crls;
    }
}
