| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.provider.certpath;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
import java.net.URI;  | 
 | 
import java.security.*;  | 
 | 
import java.security.cert.*;  | 
 | 
import javax.security.auth.x500.X500Principal;  | 
 | 
import java.util.*;  | 
 | 
 | 
 | 
import sun.security.util.Debug;  | 
 | 
import sun.security.validator.Validator;  | 
 | 
import static sun.security.x509.PKIXExtensions.*;  | 
 | 
import sun.security.x509.*;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public class DistributionPointFetcher { | 
 | 
 | 
 | 
    private static final Debug debug = Debug.getInstance("certpath"); | 
 | 
 | 
 | 
    private static final boolean[] ALL_REASONS =  | 
 | 
        {true, true, true, true, true, true, true, true, true}; | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private DistributionPointFetcher() {} | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public static Collection<X509CRL> getCRLs(X509CRLSelector selector,  | 
 | 
            boolean signFlag, PublicKey prevKey, String provider,  | 
 | 
            List<CertStore> certStores, boolean[] reasonsMask,  | 
 | 
            Set<TrustAnchor> trustAnchors, Date validity, String variant)  | 
 | 
            throws CertStoreException  | 
 | 
    { | 
 | 
        return getCRLs(selector, signFlag, prevKey, null, provider, certStores,  | 
 | 
                reasonsMask, trustAnchors, validity, variant, null);  | 
 | 
    }  | 
 | 
    /**  | 
 | 
     * Return the X509CRLs matching this selector. The selector must be  | 
 | 
     * an X509CRLSelector with certificateChecking set.  | 
 | 
     */  | 
 | 
      | 
 | 
    public static Collection<X509CRL> getCRLs(X509CRLSelector selector,  | 
 | 
                                              boolean signFlag,  | 
 | 
                                              PublicKey prevKey,  | 
 | 
                                              String provider,  | 
 | 
                                              List<CertStore> certStores,  | 
 | 
                                              boolean[] reasonsMask,  | 
 | 
                                              Set<TrustAnchor> trustAnchors,  | 
 | 
                                              Date validity)  | 
 | 
        throws CertStoreException  | 
 | 
    { | 
 | 
        if (trustAnchors.isEmpty()) { | 
 | 
            throw new CertStoreException(  | 
 | 
                "at least one TrustAnchor must be specified");  | 
 | 
        }  | 
 | 
        TrustAnchor anchor = trustAnchors.iterator().next();  | 
 | 
        return getCRLs(selector, signFlag, prevKey, null, provider, certStores,  | 
 | 
                reasonsMask, trustAnchors, validity,  | 
 | 
                Validator.VAR_PLUGIN_CODE_SIGNING, anchor);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public static Collection<X509CRL> getCRLs(X509CRLSelector selector,  | 
 | 
                                              boolean signFlag,  | 
 | 
                                              PublicKey prevKey,  | 
 | 
                                              X509Certificate prevCert,  | 
 | 
                                              String provider,  | 
 | 
                                              List<CertStore> certStores,  | 
 | 
                                              boolean[] reasonsMask,  | 
 | 
                                              Set<TrustAnchor> trustAnchors,  | 
 | 
                                              Date validity,  | 
 | 
                                              String variant,  | 
 | 
                                              TrustAnchor anchor)  | 
 | 
        throws CertStoreException  | 
 | 
    { | 
 | 
        X509Certificate cert = selector.getCertificateChecking();  | 
 | 
        if (cert == null) { | 
 | 
            return Collections.emptySet();  | 
 | 
        }  | 
 | 
        try { | 
 | 
            X509CertImpl certImpl = X509CertImpl.toImpl(cert);  | 
 | 
            if (debug != null) { | 
 | 
                debug.println("DistributionPointFetcher.getCRLs: Checking " | 
 | 
                        + "CRLDPs for " + certImpl.getSubjectX500Principal());  | 
 | 
            }  | 
 | 
            CRLDistributionPointsExtension ext =  | 
 | 
                certImpl.getCRLDistributionPointsExtension();  | 
 | 
            if (ext == null) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("No CRLDP ext"); | 
 | 
                }  | 
 | 
                return Collections.emptySet();  | 
 | 
            }  | 
 | 
            List<DistributionPoint> points =  | 
 | 
                    ext.get(CRLDistributionPointsExtension.POINTS);  | 
 | 
            Set<X509CRL> results = new HashSet<>();  | 
 | 
            for (Iterator<DistributionPoint> t = points.iterator();  | 
 | 
                 t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) { | 
 | 
                DistributionPoint point = t.next();  | 
 | 
                Collection<X509CRL> crls = getCRLs(selector, certImpl,  | 
 | 
                    point, reasonsMask, signFlag, prevKey, prevCert, provider,  | 
 | 
                    certStores, trustAnchors, validity, variant, anchor);  | 
 | 
                results.addAll(crls);  | 
 | 
            }  | 
 | 
            if (debug != null) { | 
 | 
                debug.println("Returning " + results.size() + " CRLs"); | 
 | 
            }  | 
 | 
            return results;  | 
 | 
        } catch (CertificateException | IOException e) { | 
 | 
            return Collections.emptySet();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static Collection<X509CRL> getCRLs(X509CRLSelector selector,  | 
 | 
        X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,  | 
 | 
        boolean signFlag, PublicKey prevKey, X509Certificate prevCert,  | 
 | 
        String provider, List<CertStore> certStores,  | 
 | 
        Set<TrustAnchor> trustAnchors, Date validity, String variant,  | 
 | 
        TrustAnchor anchor)  | 
 | 
            throws CertStoreException { | 
 | 
 | 
 | 
          | 
 | 
        GeneralNames fullName = point.getFullName();  | 
 | 
        if (fullName == null) { | 
 | 
              | 
 | 
            RDN relativeName = point.getRelativeName();  | 
 | 
            if (relativeName == null) { | 
 | 
                return Collections.emptySet();  | 
 | 
            }  | 
 | 
            try { | 
 | 
                GeneralNames crlIssuers = point.getCRLIssuer();  | 
 | 
                if (crlIssuers == null) { | 
 | 
                    fullName = getFullNames  | 
 | 
                        ((X500Name) certImpl.getIssuerDN(), relativeName);  | 
 | 
                } else { | 
 | 
                      | 
 | 
                    if (crlIssuers.size() != 1) { | 
 | 
                        return Collections.emptySet();  | 
 | 
                    } else { | 
 | 
                        fullName = getFullNames  | 
 | 
                            ((X500Name) crlIssuers.get(0).getName(), relativeName);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } catch (IOException ioe) { | 
 | 
                return Collections.emptySet();  | 
 | 
            }  | 
 | 
        }  | 
 | 
        Collection<X509CRL> possibleCRLs = new ArrayList<>();  | 
 | 
        CertStoreException savedCSE = null;  | 
 | 
        for (Iterator<GeneralName> t = fullName.iterator(); t.hasNext(); ) { | 
 | 
            try { | 
 | 
                GeneralName name = t.next();  | 
 | 
                if (name.getType() == GeneralNameInterface.NAME_DIRECTORY) { | 
 | 
                    X500Name x500Name = (X500Name) name.getName();  | 
 | 
                    possibleCRLs.addAll(  | 
 | 
                        getCRLs(x500Name, certImpl.getIssuerX500Principal(),  | 
 | 
                                certStores));  | 
 | 
                } else if (name.getType() == GeneralNameInterface.NAME_URI) { | 
 | 
                    URIName uriName = (URIName)name.getName();  | 
 | 
                    X509CRL crl = getCRL(uriName);  | 
 | 
                    if (crl != null) { | 
 | 
                        possibleCRLs.add(crl);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } catch (CertStoreException cse) { | 
 | 
                savedCSE = cse;  | 
 | 
            }  | 
 | 
        }  | 
 | 
          | 
 | 
        if (possibleCRLs.isEmpty() && savedCSE != null) { | 
 | 
            throw savedCSE;  | 
 | 
        }  | 
 | 
 | 
 | 
        Collection<X509CRL> crls = new ArrayList<>(2);  | 
 | 
        for (X509CRL crl : possibleCRLs) { | 
 | 
            try { | 
 | 
                // make sure issuer is not set  | 
 | 
                  | 
 | 
                selector.setIssuerNames(null);  | 
 | 
                if (selector.match(crl) && verifyCRL(certImpl, point, crl,  | 
 | 
                        reasonsMask, signFlag, prevKey, prevCert, provider,  | 
 | 
                        trustAnchors, certStores, validity, variant, anchor)) { | 
 | 
                    crls.add(crl);  | 
 | 
                }  | 
 | 
            } catch (IOException | CRLException e) { | 
 | 
                  | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("Exception verifying CRL: " + e.getMessage()); | 
 | 
                    e.printStackTrace();  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return crls;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private static X509CRL getCRL(URIName name) throws CertStoreException { | 
 | 
        URI uri = name.getURI();  | 
 | 
        if (debug != null) { | 
 | 
            debug.println("Trying to fetch CRL from DP " + uri); | 
 | 
        }  | 
 | 
        CertStore ucs = null;  | 
 | 
        try { | 
 | 
            ucs = URICertStore.getInstance  | 
 | 
                (new URICertStore.URICertStoreParameters(uri));  | 
 | 
        } catch (InvalidAlgorithmParameterException |  | 
 | 
                 NoSuchAlgorithmException e) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("Can't create URICertStore: " + e.getMessage()); | 
 | 
            }  | 
 | 
            return null;  | 
 | 
        }  | 
 | 
 | 
 | 
        Collection<? extends CRL> crls = ucs.getCRLs(null);  | 
 | 
        if (crls.isEmpty()) { | 
 | 
            return null;  | 
 | 
        } else { | 
 | 
            return (X509CRL) crls.iterator().next();  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static Collection<X509CRL> getCRLs(X500Name name,  | 
 | 
                                               X500Principal certIssuer,  | 
 | 
                                               List<CertStore> certStores)  | 
 | 
        throws CertStoreException  | 
 | 
    { | 
 | 
        if (debug != null) { | 
 | 
            debug.println("Trying to fetch CRL from DP " + name); | 
 | 
        }  | 
 | 
        X509CRLSelector xcs = new X509CRLSelector();  | 
 | 
        xcs.addIssuer(name.asX500Principal());  | 
 | 
        xcs.addIssuer(certIssuer);  | 
 | 
        Collection<X509CRL> crls = new ArrayList<>();  | 
 | 
        CertStoreException savedCSE = null;  | 
 | 
        for (CertStore store : certStores) { | 
 | 
            try { | 
 | 
                for (CRL crl : store.getCRLs(xcs)) { | 
 | 
                    crls.add((X509CRL)crl);  | 
 | 
                }  | 
 | 
            } catch (CertStoreException cse) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("Exception while retrieving " + | 
 | 
                        "CRLs: " + cse);  | 
 | 
                    cse.printStackTrace();  | 
 | 
                }  | 
 | 
                savedCSE = new PKIX.CertStoreTypeException(store.getType(),cse);  | 
 | 
            }  | 
 | 
        }  | 
 | 
          | 
 | 
        if (crls.isEmpty() && savedCSE != null) { | 
 | 
            throw savedCSE;  | 
 | 
        } else { | 
 | 
            return crls;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,  | 
 | 
        X509CRL crl, boolean[] reasonsMask, boolean signFlag,  | 
 | 
        PublicKey prevKey, X509Certificate prevCert, String provider,  | 
 | 
        Set<TrustAnchor> trustAnchors, List<CertStore> certStores,  | 
 | 
        Date validity, String variant, TrustAnchor anchor)  | 
 | 
        throws CRLException, IOException { | 
 | 
 | 
 | 
        if (debug != null) { | 
 | 
            debug.println("DistributionPointFetcher.verifyCRL: " + | 
 | 
                "checking revocation status for" +  | 
 | 
                "\n  SN: " + Debug.toHexString(certImpl.getSerialNumber()) +  | 
 | 
                "\n  Subject: " + certImpl.getSubjectX500Principal() +  | 
 | 
                "\n  Issuer: " + certImpl.getIssuerX500Principal());  | 
 | 
        }  | 
 | 
 | 
 | 
        boolean indirectCRL = false;  | 
 | 
        X509CRLImpl crlImpl = X509CRLImpl.toImpl(crl);  | 
 | 
        IssuingDistributionPointExtension idpExt =  | 
 | 
            crlImpl.getIssuingDistributionPointExtension();  | 
 | 
        X500Name certIssuer = (X500Name) certImpl.getIssuerDN();  | 
 | 
        X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();  | 
 | 
 | 
 | 
        // if crlIssuer is set, verify that it matches the issuer of the  | 
 | 
        // CRL and the CRL contains an IDP extension with the indirectCRL  | 
 | 
        // boolean asserted. Otherwise, verify that the CRL issuer matches the  | 
 | 
          | 
 | 
        GeneralNames pointCrlIssuers = point.getCRLIssuer();  | 
 | 
        X500Name pointCrlIssuer = null;  | 
 | 
        if (pointCrlIssuers != null) { | 
 | 
            if (idpExt == null ||  | 
 | 
                ((Boolean) idpExt.get  | 
 | 
                    (IssuingDistributionPointExtension.INDIRECT_CRL)).equals  | 
 | 
                        (Boolean.FALSE)) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
            boolean match = false;  | 
 | 
            for (Iterator<GeneralName> t = pointCrlIssuers.iterator();  | 
 | 
                 !match && t.hasNext(); ) { | 
 | 
                GeneralNameInterface name = t.next().getName();  | 
 | 
                if (crlIssuer.equals(name) == true) { | 
 | 
                    pointCrlIssuer = (X500Name) name;  | 
 | 
                    match = true;  | 
 | 
                }  | 
 | 
            }  | 
 | 
            if (match == false) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
 | 
 | 
            // we accept the case that a CRL issuer provide status  | 
 | 
              | 
 | 
            if (issues(certImpl, crlImpl, provider)) { | 
 | 
                  | 
 | 
                prevKey = certImpl.getPublicKey();  | 
 | 
            } else { | 
 | 
                indirectCRL = true;  | 
 | 
            }  | 
 | 
        } else if (crlIssuer.equals(certIssuer) == false) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("crl issuer does not equal cert issuer.\n" + | 
 | 
                              "crl issuer: " + crlIssuer + "\n" +  | 
 | 
                              "cert issuer: " + certIssuer);  | 
 | 
            }  | 
 | 
            return false;  | 
 | 
        } else { | 
 | 
              | 
 | 
            KeyIdentifier certAKID = certImpl.getAuthKeyId();  | 
 | 
            KeyIdentifier crlAKID = crlImpl.getAuthKeyId();  | 
 | 
 | 
 | 
            if (certAKID == null || crlAKID == null) { | 
 | 
                // cannot recognize indirect CRL without AKID  | 
 | 
 | 
 | 
                // we accept the case that a CRL issuer provide status  | 
 | 
                  | 
 | 
                if (issues(certImpl, crlImpl, provider)) { | 
 | 
                      | 
 | 
                    prevKey = certImpl.getPublicKey();  | 
 | 
                }  | 
 | 
            } else if (!certAKID.equals(crlAKID)) { | 
 | 
                // we accept the case that a CRL issuer provide status  | 
 | 
                  | 
 | 
                if (issues(certImpl, crlImpl, provider)) { | 
 | 
                      | 
 | 
                    prevKey = certImpl.getPublicKey();  | 
 | 
                } else { | 
 | 
                    indirectCRL = true;  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        if (!indirectCRL && !signFlag) { | 
 | 
              | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
        if (idpExt != null) { | 
 | 
            DistributionPointName idpPoint = (DistributionPointName)  | 
 | 
                idpExt.get(IssuingDistributionPointExtension.POINT);  | 
 | 
            if (idpPoint != null) { | 
 | 
                GeneralNames idpNames = idpPoint.getFullName();  | 
 | 
                if (idpNames == null) { | 
 | 
                    RDN relativeName = idpPoint.getRelativeName();  | 
 | 
                    if (relativeName == null) { | 
 | 
                        if (debug != null) { | 
 | 
                           debug.println("IDP must be relative or full DN"); | 
 | 
                        }  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                    if (debug != null) { | 
 | 
                        debug.println("IDP relativeName:" + relativeName); | 
 | 
                    }  | 
 | 
                    idpNames = getFullNames(crlIssuer, relativeName);  | 
 | 
                }  | 
 | 
                // if the DP name is present in the IDP CRL extension and the  | 
 | 
                // DP field is present in the DP, then verify that one of the  | 
 | 
                  | 
 | 
                if (point.getFullName() != null ||  | 
 | 
                    point.getRelativeName() != null) { | 
 | 
                    GeneralNames pointNames = point.getFullName();  | 
 | 
                    if (pointNames == null) { | 
 | 
                        RDN relativeName = point.getRelativeName();  | 
 | 
                        if (relativeName == null) { | 
 | 
                            if (debug != null) { | 
 | 
                                debug.println("DP must be relative or full DN"); | 
 | 
                            }  | 
 | 
                            return false;  | 
 | 
                        }  | 
 | 
                        if (debug != null) { | 
 | 
                            debug.println("DP relativeName:" + relativeName); | 
 | 
                        }  | 
 | 
                        if (indirectCRL) { | 
 | 
                            if (pointCrlIssuers.size() != 1) { | 
 | 
                                // RFC 5280: there must be only 1 CRL issuer  | 
 | 
                                  | 
 | 
                                if (debug != null) { | 
 | 
                                    debug.println("must only be one CRL " + | 
 | 
                                        "issuer when relative name present");  | 
 | 
                                }  | 
 | 
                                return false;  | 
 | 
                            }  | 
 | 
                            pointNames = getFullNames  | 
 | 
                                (pointCrlIssuer, relativeName);  | 
 | 
                        } else { | 
 | 
                            pointNames = getFullNames(certIssuer, relativeName);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    boolean match = false;  | 
 | 
                    for (Iterator<GeneralName> i = idpNames.iterator();  | 
 | 
                         !match && i.hasNext(); ) { | 
 | 
                        GeneralNameInterface idpName = i.next().getName();  | 
 | 
                        if (debug != null) { | 
 | 
                            debug.println("idpName: " + idpName); | 
 | 
                        }  | 
 | 
                        for (Iterator<GeneralName> p = pointNames.iterator();  | 
 | 
                             !match && p.hasNext(); ) { | 
 | 
                            GeneralNameInterface pointName = p.next().getName();  | 
 | 
                            if (debug != null) { | 
 | 
                                debug.println("pointName: " + pointName); | 
 | 
                            }  | 
 | 
                            match = idpName.equals(pointName);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    if (!match) { | 
 | 
                        if (debug != null) { | 
 | 
                            debug.println("IDP name does not match DP name"); | 
 | 
                        }  | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                // if the DP name is present in the IDP CRL extension and the  | 
 | 
                // DP field is absent from the DP, then verify that one of the  | 
 | 
                // names in the IDP matches one of the names in the crlIssuer  | 
 | 
                // field of the DP  | 
 | 
                } else { | 
 | 
                    // verify that one of the names in the IDP matches one of  | 
 | 
                      | 
 | 
                    boolean match = false;  | 
 | 
                    for (Iterator<GeneralName> t = pointCrlIssuers.iterator();  | 
 | 
                         !match && t.hasNext(); ) { | 
 | 
                        GeneralNameInterface crlIssuerName = t.next().getName();  | 
 | 
                        for (Iterator<GeneralName> i = idpNames.iterator();  | 
 | 
                             !match && i.hasNext(); ) { | 
 | 
                            GeneralNameInterface idpName = i.next().getName();  | 
 | 
                            match = crlIssuerName.equals(idpName);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    if (!match) { | 
 | 
                        return false;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
            // if the onlyContainsUserCerts boolean is asserted, verify that the  | 
 | 
              | 
 | 
            Boolean b = (Boolean)  | 
 | 
                idpExt.get(IssuingDistributionPointExtension.ONLY_USER_CERTS);  | 
 | 
            if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() != -1) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("cert must be a EE cert"); | 
 | 
                }  | 
 | 
                return false;  | 
 | 
            }  | 
 | 
 | 
 | 
            // if the onlyContainsCACerts boolean is asserted, verify that the  | 
 | 
              | 
 | 
            b = (Boolean)  | 
 | 
                idpExt.get(IssuingDistributionPointExtension.ONLY_CA_CERTS);  | 
 | 
            if (b.equals(Boolean.TRUE) && certImpl.getBasicConstraints() == -1) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("cert must be a CA cert"); | 
 | 
                }  | 
 | 
                return false;  | 
 | 
            }  | 
 | 
 | 
 | 
            // verify that the onlyContainsAttributeCerts boolean is not  | 
 | 
              | 
 | 
            b = (Boolean) idpExt.get  | 
 | 
                (IssuingDistributionPointExtension.ONLY_ATTRIBUTE_CERTS);  | 
 | 
            if (b.equals(Boolean.TRUE)) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("cert must not be an AA cert"); | 
 | 
                }  | 
 | 
                return false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        boolean[] interimReasonsMask = new boolean[9];  | 
 | 
        ReasonFlags reasons = null;  | 
 | 
        if (idpExt != null) { | 
 | 
            reasons = (ReasonFlags)  | 
 | 
                idpExt.get(IssuingDistributionPointExtension.REASONS);  | 
 | 
        }  | 
 | 
 | 
 | 
        boolean[] pointReasonFlags = point.getReasonFlags();  | 
 | 
        if (reasons != null) { | 
 | 
            if (pointReasonFlags != null) { | 
 | 
                // set interim reasons mask to the intersection of  | 
 | 
                  | 
 | 
                boolean[] idpReasonFlags = reasons.getFlags();  | 
 | 
                for (int i = 0; i < interimReasonsMask.length; i++) { | 
 | 
                    interimReasonsMask[i] =  | 
 | 
                        (i < idpReasonFlags.length && idpReasonFlags[i]) &&  | 
 | 
                        (i < pointReasonFlags.length && pointReasonFlags[i]);  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                // set interim reasons mask to the value of  | 
 | 
                // onlySomeReasons in the IDP (and clone it since we may  | 
 | 
                  | 
 | 
                interimReasonsMask = reasons.getFlags().clone();  | 
 | 
            }  | 
 | 
        } else if (idpExt == null || reasons == null) { | 
 | 
            if (pointReasonFlags != null) { | 
 | 
                  | 
 | 
                interimReasonsMask = pointReasonFlags.clone();  | 
 | 
            } else { | 
 | 
                  | 
 | 
                Arrays.fill(interimReasonsMask, true);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        // verify that interim reasons mask includes one or more reasons  | 
 | 
          | 
 | 
        boolean oneOrMore = false;  | 
 | 
        for (int i = 0; i < interimReasonsMask.length && !oneOrMore; i++) { | 
 | 
            if (interimReasonsMask[i] &&  | 
 | 
                    !(i < reasonsMask.length && reasonsMask[i]))  | 
 | 
            { | 
 | 
                oneOrMore = true;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (!oneOrMore) { | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
        // Obtain and validate the certification path for the complete  | 
 | 
        // CRL issuer (if indirect CRL). If a key usage extension is present  | 
 | 
          | 
 | 
        if (indirectCRL) { | 
 | 
            X509CertSelector certSel = new X509CertSelector();  | 
 | 
            certSel.setSubject(crlIssuer.asX500Principal());  | 
 | 
            boolean[] crlSign = {false,false,false,false,false,false,true}; | 
 | 
            certSel.setKeyUsage(crlSign);  | 
 | 
 | 
 | 
            // Currently by default, forward builder does not enable  | 
 | 
            // subject/authority key identifier identifying for target  | 
 | 
            // certificate, instead, it only compares the CRL issuer and  | 
 | 
            // the target certificate subject. If the certificate of the  | 
 | 
            // delegated CRL issuer is a self-issued certificate, the  | 
 | 
            // builder is unable to find the proper CRL issuer by issuer  | 
 | 
            // name only, there is a potential dead loop on finding the  | 
 | 
            // proper issuer. It is of great help to narrow the target  | 
 | 
            // scope down to aware of authority key identifiers in the  | 
 | 
              | 
 | 
            AuthorityKeyIdentifierExtension akidext =  | 
 | 
                                            crlImpl.getAuthKeyIdExtension();  | 
 | 
            if (akidext != null) { | 
 | 
                byte[] kid = akidext.getEncodedKeyIdentifier();  | 
 | 
                if (kid != null) { | 
 | 
                    certSel.setSubjectKeyIdentifier(kid);  | 
 | 
                }  | 
 | 
 | 
 | 
                SerialNumber asn = (SerialNumber)akidext.get(  | 
 | 
                        AuthorityKeyIdentifierExtension.SERIAL_NUMBER);  | 
 | 
                if (asn != null) { | 
 | 
                    certSel.setSerialNumber(asn.getNumber());  | 
 | 
                }  | 
 | 
                // the subject criterion will be set by builder automatically.  | 
 | 
            }  | 
 | 
 | 
 | 
            // By now, we have validated the previous certificate, so we can  | 
 | 
            // trust it during the validation of the CRL issuer.  | 
 | 
            // In addition to the performance improvement, another benefit is to  | 
 | 
            // break the dead loop while looking for the issuer back and forth  | 
 | 
              | 
 | 
            Set<TrustAnchor> newTrustAnchors = new HashSet<>(trustAnchors);  | 
 | 
 | 
 | 
            if (prevKey != null) { | 
 | 
                // Add the previous certificate as a trust anchor.  | 
 | 
                // If prevCert is not null, we want to construct a TrustAnchor  | 
 | 
                // using the cert object because when the certpath for the CRL  | 
 | 
                // is built later, the CertSelector will make comparisons with  | 
 | 
                  | 
 | 
                TrustAnchor temporary;  | 
 | 
                if (prevCert != null) { | 
 | 
                    temporary = new TrustAnchor(prevCert, null);  | 
 | 
                } else { | 
 | 
                    X500Principal principal = certImpl.getIssuerX500Principal();  | 
 | 
                    temporary = new TrustAnchor(principal, prevKey, null);  | 
 | 
                }  | 
 | 
                newTrustAnchors.add(temporary);  | 
 | 
            }  | 
 | 
 | 
 | 
            PKIXBuilderParameters params = null;  | 
 | 
            try { | 
 | 
                params = new PKIXBuilderParameters(newTrustAnchors, certSel);  | 
 | 
            } catch (InvalidAlgorithmParameterException iape) { | 
 | 
                throw new CRLException(iape);  | 
 | 
            }  | 
 | 
            params.setCertStores(certStores);  | 
 | 
            params.setSigProvider(provider);  | 
 | 
            params.setDate(validity);  | 
 | 
            try { | 
 | 
                CertPathBuilder builder = CertPathBuilder.getInstance("PKIX"); | 
 | 
                PKIXCertPathBuilderResult result =  | 
 | 
                    (PKIXCertPathBuilderResult) builder.build(params);  | 
 | 
                prevKey = result.getPublicKey();  | 
 | 
            } catch (GeneralSecurityException e) { | 
 | 
                throw new CRLException(e);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        try { | 
 | 
            AlgorithmChecker.check(prevKey, crl, variant, anchor);  | 
 | 
        } catch (CertPathValidatorException cpve) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("CRL signature algorithm check failed: " + cpve); | 
 | 
            }  | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        try { | 
 | 
            crl.verify(prevKey, provider);  | 
 | 
        } catch (GeneralSecurityException e) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("CRL signature failed to verify"); | 
 | 
            }  | 
 | 
            return false;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        Set<String> unresCritExts = crl.getCriticalExtensionOIDs();  | 
 | 
          | 
 | 
        if (unresCritExts != null) { | 
 | 
            unresCritExts.remove(IssuingDistributionPoint_Id.toString());  | 
 | 
            if (!unresCritExts.isEmpty()) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("Unrecognized critical extension(s) in CRL: " | 
 | 
                        + unresCritExts);  | 
 | 
                    for (String ext : unresCritExts) { | 
 | 
                        debug.println(ext);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                return false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        for (int i = 0; i < reasonsMask.length; i++) { | 
 | 
            reasonsMask[i] = reasonsMask[i] ||  | 
 | 
                    (i < interimReasonsMask.length && interimReasonsMask[i]);  | 
 | 
        }  | 
 | 
 | 
 | 
        return true;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static GeneralNames getFullNames(X500Name issuer, RDN rdn)  | 
 | 
        throws IOException  | 
 | 
    { | 
 | 
        List<RDN> rdns = new ArrayList<>(issuer.rdns());  | 
 | 
        rdns.add(rdn);  | 
 | 
        X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));  | 
 | 
        GeneralNames fullNames = new GeneralNames();  | 
 | 
        fullNames.add(new GeneralName(fullName));  | 
 | 
        return fullNames;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private static boolean issues(X509CertImpl cert, X509CRLImpl crl,  | 
 | 
                                  String provider) throws IOException  | 
 | 
    { | 
 | 
        boolean matched = false;  | 
 | 
 | 
 | 
        AdaptableX509CertSelector issuerSelector =  | 
 | 
                                    new AdaptableX509CertSelector();  | 
 | 
 | 
 | 
          | 
 | 
        boolean[] usages = cert.getKeyUsage();  | 
 | 
        if (usages != null) { | 
 | 
            usages[6] = true;         | 
 | 
            issuerSelector.setKeyUsage(usages);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        X500Principal crlIssuer = crl.getIssuerX500Principal();  | 
 | 
        issuerSelector.setSubject(crlIssuer);  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        AuthorityKeyIdentifierExtension crlAKID = crl.getAuthKeyIdExtension();  | 
 | 
        issuerSelector.setSkiAndSerialNumber(crlAKID);  | 
 | 
 | 
 | 
        matched = issuerSelector.match(cert);  | 
 | 
 | 
 | 
          | 
 | 
        if (matched && (crlAKID == null ||  | 
 | 
                cert.getAuthorityKeyIdentifierExtension() == null)) { | 
 | 
            try { | 
 | 
                crl.verify(cert.getPublicKey(), provider);  | 
 | 
                matched = true;  | 
 | 
            } catch (GeneralSecurityException e) { | 
 | 
                matched = false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        return matched;  | 
 | 
    }  | 
 | 
}  |