| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.provider.certpath.ldap;  | 
 | 
 | 
 | 
import java.io.ByteArrayInputStream;  | 
 | 
import java.io.IOException;  | 
 | 
import java.math.BigInteger;  | 
 | 
import java.net.URI;  | 
 | 
import java.util.*;  | 
 | 
import javax.naming.Context;  | 
 | 
import javax.naming.CompositeName;  | 
 | 
import javax.naming.InvalidNameException;  | 
 | 
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 javax.naming.directory.DirContext;  | 
 | 
import javax.naming.directory.InitialDirContext;  | 
 | 
 | 
 | 
import java.security.*;  | 
 | 
import java.security.cert.Certificate;  | 
 | 
import java.security.cert.*;  | 
 | 
import javax.naming.ldap.LdapContext;  | 
 | 
import javax.security.auth.x500.X500Principal;  | 
 | 
 | 
 | 
import com.sun.jndi.ldap.LdapReferralException;  | 
 | 
import sun.misc.HexDumpEncoder;  | 
 | 
import sun.security.provider.certpath.X509CertificatePair;  | 
 | 
import sun.security.util.Cache;  | 
 | 
import sun.security.util.Debug;  | 
 | 
import sun.security.x509.X500Name;  | 
 | 
import sun.security.action.GetBooleanAction;  | 
 | 
import sun.security.action.GetPropertyAction;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public final class LDAPCertStore extends CertStoreSpi { | 
 | 
 | 
 | 
    private static final Debug debug = Debug.getInstance("certpath"); | 
 | 
 | 
 | 
    private final static boolean DEBUG = false;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    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";  | 
 | 
 | 
 | 
      | 
 | 
    private final static String[] STRING0 = new String[0];  | 
 | 
 | 
 | 
    private final static byte[][] BB0 = new byte[0][];  | 
 | 
 | 
 | 
    private final static Attributes EMPTY_ATTRIBUTES = new BasicAttributes();  | 
 | 
 | 
 | 
      | 
 | 
    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";  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private final static String PROP_DISABLE_APP_RESOURCE_FILES =  | 
 | 
        "sun.security.certpath.ldap.disable.app.resource.files";  | 
 | 
 | 
 | 
    static { | 
 | 
        String s = AccessController.doPrivileged(  | 
 | 
                                new GetPropertyAction(PROP_LIFETIME));  | 
 | 
        if (s != null) { | 
 | 
            LIFETIME = Integer.parseInt(s);   | 
 | 
        } else { | 
 | 
            LIFETIME = DEFAULT_CACHE_LIFETIME;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private CertificateFactory cf;  | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private DirContext ctx;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private boolean prefetchCRLs = false;  | 
 | 
 | 
 | 
    private final Cache<String, byte[][]> valueCache;  | 
 | 
 | 
 | 
    private int cacheHits = 0;  | 
 | 
    private int cacheMisses = 0;  | 
 | 
    private int requests = 0;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public LDAPCertStore(CertStoreParameters params)  | 
 | 
            throws InvalidAlgorithmParameterException { | 
 | 
        super(params);  | 
 | 
        if (!(params instanceof LDAPCertStoreParameters))  | 
 | 
          throw new InvalidAlgorithmParameterException(  | 
 | 
            "parameters must be LDAPCertStoreParameters");  | 
 | 
 | 
 | 
        LDAPCertStoreParameters lparams = (LDAPCertStoreParameters) params;  | 
 | 
 | 
 | 
          | 
 | 
        createInitialDirContext(lparams.getServerName(), lparams.getPort());  | 
 | 
 | 
 | 
          | 
 | 
        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);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static final Cache<LDAPCertStoreParameters, CertStore>  | 
 | 
        certStoreCache = Cache.newSoftMemoryCache(185);  | 
 | 
    static synchronized CertStore getInstance(LDAPCertStoreParameters params)  | 
 | 
        throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { | 
 | 
 | 
 | 
        SecurityManager security = System.getSecurityManager();  | 
 | 
        if (security != null) { | 
 | 
            security.checkConnect(params.getServerName(), params.getPort());  | 
 | 
        }  | 
 | 
 | 
 | 
        CertStore lcs = certStoreCache.get(params);  | 
 | 
        if (lcs == null) { | 
 | 
            lcs = CertStore.getInstance("LDAP", params); | 
 | 
            certStoreCache.put(params, lcs);  | 
 | 
        } else { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("LDAPCertStore.getInstance: cache hit"); | 
 | 
            }  | 
 | 
        }  | 
 | 
        return lcs;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    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);  | 
 | 
 | 
 | 
          | 
 | 
        boolean disableAppResourceFiles = AccessController.doPrivileged(  | 
 | 
            new GetBooleanAction(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 InitialDirContext(env);  | 
 | 
              | 
 | 
 | 
 | 
 | 
 | 
             */  | 
 | 
            Hashtable<?,?> currentEnv = ctx.getEnvironment();  | 
 | 
            if (currentEnv.get(Context.REFERRAL) == null) { | 
 | 
                ctx.addToEnvironment(Context.REFERRAL, "throw");  | 
 | 
            }  | 
 | 
        } 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 LDAPRequest { | 
 | 
 | 
 | 
        private final String name;  | 
 | 
        private Map<String, byte[][]> valueMap;  | 
 | 
        private final List<String> requestedAttributes;  | 
 | 
 | 
 | 
        LDAPRequest(String name) throws CertStoreException { | 
 | 
            this.name = checkName(name);  | 
 | 
            requestedAttributes = new ArrayList<>(5);  | 
 | 
        }  | 
 | 
 | 
 | 
        private String checkName(String name) throws CertStoreException { | 
 | 
            if (name == null) { | 
 | 
                throw new CertStoreException("Name absent"); | 
 | 
            }  | 
 | 
            try { | 
 | 
                if (new CompositeName(name).size() > 1) { | 
 | 
                    throw new CertStoreException("Invalid name: " + name); | 
 | 
                }  | 
 | 
            } catch (InvalidNameException ine) { | 
 | 
                throw new CertStoreException("Invalid name: " + name, ine); | 
 | 
            }  | 
 | 
            return name;  | 
 | 
        }  | 
 | 
 | 
 | 
        String getName() { | 
 | 
            return name;  | 
 | 
        }  | 
 | 
 | 
 | 
        void addRequestedAttribute(String attrId) { | 
 | 
            if (valueMap != null) { | 
 | 
                throw new IllegalStateException("Request already sent"); | 
 | 
            }  | 
 | 
            requestedAttributes.add(attrId);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        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;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        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;  | 
 | 
            try { | 
 | 
                attrs = ctx.getAttributes(name, attrIds);  | 
 | 
            } catch (LdapReferralException lre) { | 
 | 
                  | 
 | 
                while (true) { | 
 | 
                    try { | 
 | 
                        String newName = (String) lre.getReferralInfo();  | 
 | 
                        URI newUri = new URI(newName);  | 
 | 
                        if (!newUri.getScheme().equalsIgnoreCase("ldap")) { | 
 | 
                            throw new IllegalArgumentException("Not LDAP"); | 
 | 
                        }  | 
 | 
                        String newDn = newUri.getPath();  | 
 | 
                        if (newDn != null && newDn.charAt(0) == '/') { | 
 | 
                            newDn = newDn.substring(1);  | 
 | 
                        }  | 
 | 
                        checkName(newDn);  | 
 | 
                    } catch (Exception e) { | 
 | 
                        throw new NamingException("Cannot follow referral to " | 
 | 
                                + lre.getReferralInfo());  | 
 | 
                    }  | 
 | 
                    LdapContext refCtx =  | 
 | 
                            (LdapContext)lre.getReferralContext();  | 
 | 
 | 
 | 
                      | 
 | 
                    try { | 
 | 
                        attrs = refCtx.getAttributes(name, attrIds);  | 
 | 
                        break;  | 
 | 
                    } catch (LdapReferralException re) { | 
 | 
                        lre = re;  | 
 | 
                        continue;  | 
 | 
                    } finally { | 
 | 
                          | 
 | 
                        refCtx.close();  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } catch (NameNotFoundException e) { | 
 | 
                // name does not exist on this LDAP server  | 
 | 
                  | 
 | 
                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;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         */  | 
 | 
        private void cacheAttribute(String attrId, byte[][] values) { | 
 | 
            String cacheKey = name + "|" + attrId;  | 
 | 
            valueCache.put(cacheKey, values);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        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;  | 
 | 
        }  | 
 | 
 | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private Collection<X509Certificate> getCertificates(LDAPRequest request,  | 
 | 
        String id, X509CertSelector sel) throws CertStoreException { | 
 | 
 | 
 | 
          | 
 | 
        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);  | 
 | 
          | 
 | 
        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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private Collection<X509CertificatePair> getCertPairs(  | 
 | 
        LDAPRequest request, String id) throws CertStoreException { | 
 | 
 | 
 | 
          | 
 | 
        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);  | 
 | 
          | 
 | 
        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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private Collection<X509Certificate> getMatchingCrossCerts(  | 
 | 
            LDAPRequest request, X509CertSelector forward,  | 
 | 
            X509CertSelector reverse)  | 
 | 
            throws CertStoreException { | 
 | 
          | 
 | 
        Collection<X509CertificatePair> certPairs =  | 
 | 
                                getCertPairs(request, CROSS_CERT);  | 
 | 
 | 
 | 
          | 
 | 
        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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public synchronized Collection<X509Certificate> engineGetCertificates  | 
 | 
            (CertSelector selector) throws CertStoreException { | 
 | 
        if (debug != null) { | 
 | 
            debug.println("LDAPCertStore.engineGetCertificates() selector: " | 
 | 
                + String.valueOf(selector));  | 
 | 
        }  | 
 | 
 | 
 | 
        if (selector == null) { | 
 | 
            selector = new X509CertSelector();  | 
 | 
        }  | 
 | 
        if (!(selector instanceof X509CertSelector)) { | 
 | 
            throw new CertStoreException("LDAPCertStore needs an X509CertSelector " + | 
 | 
                                         "to find certs");  | 
 | 
        }  | 
 | 
        X509CertSelector xsel = (X509CertSelector) selector;  | 
 | 
        int basicConstraints = xsel.getBasicConstraints();  | 
 | 
        String subject = xsel.getSubjectAsString();  | 
 | 
        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  | 
 | 
          | 
 | 
        if (subject != null) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("LDAPCertStore.engineGetCertificates() " | 
 | 
                    + "subject is not null");  | 
 | 
            }  | 
 | 
            LDAPRequest request = new LDAPRequest(subject);  | 
 | 
            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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private Collection<X509CRL> getCRLs(LDAPRequest request, String id,  | 
 | 
            X509CRLSelector sel) throws CertStoreException { | 
 | 
 | 
 | 
          | 
 | 
        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);  | 
 | 
          | 
 | 
        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;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)  | 
 | 
            throws CertStoreException { | 
 | 
        if (debug != null) { | 
 | 
            debug.println("LDAPCertStore.engineGetCRLs() selector: " | 
 | 
                + selector);  | 
 | 
        }  | 
 | 
          | 
 | 
        if (selector == null) { | 
 | 
            selector = new X509CRLSelector();  | 
 | 
        }  | 
 | 
        if (!(selector instanceof X509CRLSelector)) { | 
 | 
            throw new CertStoreException("need X509CRLSelector to find CRLs"); | 
 | 
        }  | 
 | 
        X509CRLSelector xsel = (X509CRLSelector) selector;  | 
 | 
        HashSet<X509CRL> crls = new HashSet<>();  | 
 | 
 | 
 | 
          | 
 | 
        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  | 
 | 
              | 
 | 
            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;  | 
 | 
            }  | 
 | 
              | 
 | 
            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  | 
 | 
                          | 
 | 
                        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  | 
 | 
              | 
 | 
            if (entryCRLs.isEmpty() || certChecking == null) { | 
 | 
                LDAPRequest request = new LDAPRequest(issuerName);  | 
 | 
                request.addRequestedAttribute(CRL);  | 
 | 
                entryCRLs = getCRLs(request, CRL, xsel);  | 
 | 
                crls.addAll(entryCRLs);  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return crls;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    static LDAPCertStoreParameters getParameters(URI uri) { | 
 | 
        String host = uri.getHost();  | 
 | 
        if (host == null) { | 
 | 
            return new SunLDAPCertStoreParameters();  | 
 | 
        } else { | 
 | 
            int port = uri.getPort();  | 
 | 
            return (port == -1  | 
 | 
                    ? new SunLDAPCertStoreParameters(host)  | 
 | 
                    : new SunLDAPCertStoreParameters(host, port));  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static class SunLDAPCertStoreParameters  | 
 | 
        extends LDAPCertStoreParameters { | 
 | 
 | 
 | 
        private volatile int hashCode = 0;  | 
 | 
 | 
 | 
        SunLDAPCertStoreParameters(String serverName, int port) { | 
 | 
            super(serverName, port);  | 
 | 
        }  | 
 | 
        SunLDAPCertStoreParameters(String serverName) { | 
 | 
            super(serverName);  | 
 | 
        }  | 
 | 
        SunLDAPCertStoreParameters() { | 
 | 
            super();  | 
 | 
        }  | 
 | 
        public boolean equals(Object obj) { | 
 | 
            if (!(obj instanceof LDAPCertStoreParameters)) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
            LDAPCertStoreParameters params = (LDAPCertStoreParameters) obj;  | 
 | 
            return (getPort() == params.getPort() &&  | 
 | 
                    getServerName().equalsIgnoreCase(params.getServerName()));  | 
 | 
        }  | 
 | 
        public int hashCode() { | 
 | 
            if (hashCode == 0) { | 
 | 
                int result = 17;  | 
 | 
                result = 37*result + getPort();  | 
 | 
                result = 37*result +  | 
 | 
                    getServerName().toLowerCase(Locale.ENGLISH).hashCode();  | 
 | 
                hashCode = result;  | 
 | 
            }  | 
 | 
            return hashCode;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static class LDAPCertSelector extends X509CertSelector { | 
 | 
 | 
 | 
        private X500Principal certSubject;  | 
 | 
        private X509CertSelector selector;  | 
 | 
        private X500Principal subject;  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        LDAPCertSelector(X509CertSelector selector, X500Principal certSubject,  | 
 | 
            String ldapDN) throws IOException { | 
 | 
            this.selector = selector == null ? new X509CertSelector() : selector;  | 
 | 
            this.certSubject = certSubject;  | 
 | 
            this.subject = new X500Name(ldapDN).asX500Principal();  | 
 | 
        }  | 
 | 
 | 
 | 
        // we only override the get (accessor methods) since the set methods  | 
 | 
          | 
 | 
        public X509Certificate getCertificate() { | 
 | 
            return selector.getCertificate();  | 
 | 
        }  | 
 | 
        public BigInteger getSerialNumber() { | 
 | 
            return selector.getSerialNumber();  | 
 | 
        }  | 
 | 
        public X500Principal getIssuer() { | 
 | 
            return selector.getIssuer();  | 
 | 
        }  | 
 | 
        public String getIssuerAsString() { | 
 | 
            return selector.getIssuerAsString();  | 
 | 
        }  | 
 | 
        public byte[] getIssuerAsBytes() throws IOException { | 
 | 
            return selector.getIssuerAsBytes();  | 
 | 
        }  | 
 | 
        public X500Principal getSubject() { | 
 | 
              | 
 | 
            return subject;  | 
 | 
        }  | 
 | 
        public String getSubjectAsString() { | 
 | 
              | 
 | 
            return subject.getName();  | 
 | 
        }  | 
 | 
        public byte[] getSubjectAsBytes() throws IOException { | 
 | 
              | 
 | 
            return subject.getEncoded();  | 
 | 
        }  | 
 | 
        public byte[] getSubjectKeyIdentifier() { | 
 | 
            return selector.getSubjectKeyIdentifier();  | 
 | 
        }  | 
 | 
        public byte[] getAuthorityKeyIdentifier() { | 
 | 
            return selector.getAuthorityKeyIdentifier();  | 
 | 
        }  | 
 | 
        public Date getCertificateValid() { | 
 | 
            return selector.getCertificateValid();  | 
 | 
        }  | 
 | 
        public Date getPrivateKeyValid() { | 
 | 
            return selector.getPrivateKeyValid();  | 
 | 
        }  | 
 | 
        public String getSubjectPublicKeyAlgID() { | 
 | 
            return selector.getSubjectPublicKeyAlgID();  | 
 | 
        }  | 
 | 
        public PublicKey getSubjectPublicKey() { | 
 | 
            return selector.getSubjectPublicKey();  | 
 | 
        }  | 
 | 
        public boolean[] getKeyUsage() { | 
 | 
            return selector.getKeyUsage();  | 
 | 
        }  | 
 | 
        public Set<String> getExtendedKeyUsage() { | 
 | 
            return selector.getExtendedKeyUsage();  | 
 | 
        }  | 
 | 
        public boolean getMatchAllSubjectAltNames() { | 
 | 
            return selector.getMatchAllSubjectAltNames();  | 
 | 
        }  | 
 | 
        public Collection<List<?>> getSubjectAlternativeNames() { | 
 | 
            return selector.getSubjectAlternativeNames();  | 
 | 
        }  | 
 | 
        public byte[] getNameConstraints() { | 
 | 
            return selector.getNameConstraints();  | 
 | 
        }  | 
 | 
        public int getBasicConstraints() { | 
 | 
            return selector.getBasicConstraints();  | 
 | 
        }  | 
 | 
        public Set<String> getPolicy() { | 
 | 
            return selector.getPolicy();  | 
 | 
        }  | 
 | 
        public Collection<List<?>> getPathToNames() { | 
 | 
            return selector.getPathToNames();  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean match(Certificate cert) { | 
 | 
            // temporarily set the subject criterion to the certSubject  | 
 | 
              | 
 | 
            selector.setSubject(certSubject);  | 
 | 
            boolean match = selector.match(cert);  | 
 | 
            selector.setSubject(subject);  | 
 | 
            return match;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static class LDAPCRLSelector extends X509CRLSelector { | 
 | 
 | 
 | 
        private X509CRLSelector selector;  | 
 | 
        private Collection<X500Principal> certIssuers;  | 
 | 
        private Collection<X500Principal> issuers;  | 
 | 
        private HashSet<Object> issuerNames;  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        LDAPCRLSelector(X509CRLSelector selector,  | 
 | 
            Collection<X500Principal> certIssuers, String ldapDN)  | 
 | 
            throws IOException { | 
 | 
            this.selector = selector == null ? new X509CRLSelector() : selector;  | 
 | 
            this.certIssuers = certIssuers;  | 
 | 
            issuerNames = new HashSet<>();  | 
 | 
            issuerNames.add(ldapDN);  | 
 | 
            issuers = new HashSet<>();  | 
 | 
            issuers.add(new X500Name(ldapDN).asX500Principal());  | 
 | 
        }  | 
 | 
        // we only override the get (accessor methods) since the set methods  | 
 | 
          | 
 | 
        public Collection<X500Principal> getIssuers() { | 
 | 
              | 
 | 
            return Collections.unmodifiableCollection(issuers);  | 
 | 
        }  | 
 | 
        public Collection<Object> getIssuerNames() { | 
 | 
              | 
 | 
            return Collections.unmodifiableCollection(issuerNames);  | 
 | 
        }  | 
 | 
        public BigInteger getMinCRL() { | 
 | 
            return selector.getMinCRL();  | 
 | 
        }  | 
 | 
        public BigInteger getMaxCRL() { | 
 | 
            return selector.getMaxCRL();  | 
 | 
        }  | 
 | 
        public Date getDateAndTime() { | 
 | 
            return selector.getDateAndTime();  | 
 | 
        }  | 
 | 
        public X509Certificate getCertificateChecking() { | 
 | 
            return selector.getCertificateChecking();  | 
 | 
        }  | 
 | 
        public boolean match(CRL crl) { | 
 | 
            // temporarily set the issuer criterion to the certIssuers  | 
 | 
              | 
 | 
            selector.setIssuers(certIssuers);  | 
 | 
            boolean match = selector.match(crl);  | 
 | 
            selector.setIssuers(issuers);  | 
 | 
            return match;  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |