741 lines · 28.2 KB · Java
RawDownload
        // check if this certificate is appropriate for this type of use        // first check extensions, if they match, check expiration        // note: we may want to move this code into the sun.security.validator        // package        CheckResult check(X509Certificate cert, Date date) {            if (this == NONE) {                return CheckResult.OK;            }             // check extensions            try {                // check extended key usage                List<String> certEku = cert.getExtendedKeyUsage();                if ((certEku != null) &&                        Collections.disjoint(validEku, certEku)) {                    // if extension present and it does not contain any of                    // the valid EKU OIDs, return extension_mismatch                    return CheckResult.EXTENSION_MISMATCH;                }                 // check key usage                boolean[] ku = cert.getKeyUsage();                if (ku != null) {                    String algorithm = cert.getPublicKey().getAlgorithm();                    boolean kuSignature = getBit(ku, 0);                    if (algorithm.equals("RSA")) {                        // require either signature bit                        // or if server also allow key encipherment bit                        if (kuSignature == false) {                            if ((this == CLIENT) || (getBit(ku, 2) == false)) {                                return CheckResult.EXTENSION_MISMATCH;                            }                        }                    } else if (algorithm.equals("DSA")) {                        // require signature bit                        if (kuSignature == false) {                            return CheckResult.EXTENSION_MISMATCH;                        }                    } else if (algorithm.equals("DH")) {                        // require keyagreement bit                        if (getBit(ku, 4) == false) {                            return CheckResult.EXTENSION_MISMATCH;                        }                    } else if (algorithm.equals("EC")) {                        // require signature bit                        if (kuSignature == false) {                            return CheckResult.EXTENSION_MISMATCH;                        }                        // For servers, also require key agreement.                        // This is not totally accurate as the keyAgreement bit                        // is only necessary for static ECDH key exchange and                        // not ephemeral ECDH. We leave it in for now until                        // there are signs that this check causes problems                        // for real world EC certificates.                        if ((this == SERVER) && (getBit(ku, 4) == false)) {                            return CheckResult.EXTENSION_MISMATCH;                        }                    }                }            } catch (CertificateException e) {                // extensions unparseable, return failure                return CheckResult.EXTENSION_MISMATCH;            }             try {                cert.checkValidity(date);                return CheckResult.OK;            } catch (CertificateException e) {                return CheckResult.EXPIRED;            }        }    }     // enum for the result of the extension check    // NOTE: the order of the constants is important as they are used    // for sorting, i.e. OK is best, followed by EXPIRED and EXTENSION_MISMATCH    private static enum CheckResult {        OK,                     // ok or not checked        EXPIRED,                // extensions valid but cert expired        EXTENSION_MISMATCH,     // extensions invalid (expiration not checked)    }     /*     * Return a List of all candidate matches in the specified builder     * that fit the parameters.     * We exclude entries in the KeyStore if they are not:     *  . private key entries     *  . the certificates are not X509 certificates     *  . the algorithm of the key in the EE cert doesn't match one of keyTypes     *  . none of the certs is issued by a Principal in issuerSet     * Using those entries would not be possible or they would almost     * certainly be rejected by the peer.     *     * In addition to those checks, we also check the extensions in the EE     * cert and its expiration. Even if there is a mismatch, we include     * such certificates because they technically work and might be accepted     * by the peer. This leads to more graceful failure and better error     * messages if the cert expires from one day to the next.     *     * The return values are:     *   . null, if there are no matching entries at all     *   . if 'findAll' is 'false' and there is a perfect match, a List     *     with a single element (early return)     *   . if 'findAll' is 'false' and there is NO perfect match, a List     *     with all the imperfect matches (expired, wrong extensions)     *   . if 'findAll' is 'true', a List with all perfect and imperfect     *     matches     */    private List<EntryStatus> getAliases(int builderIndex,            List<KeyType> keyTypes, Set<Principal> issuerSet,            boolean findAll, CheckType checkType,            AlgorithmConstraints constraints) throws Exception {        Builder builder = builders.get(builderIndex);        KeyStore ks = builder.getKeyStore();        List<EntryStatus> results = null;        Date date = verificationDate;        boolean preferred = false;        for (Enumeration<String> e = ks.aliases(); e.hasMoreElements(); ) {            String alias = e.nextElement();            // check if it is a key entry (private key or secret key)            if (ks.isKeyEntry(alias) == false) {                continue;            }             Certificate[] chain = ks.getCertificateChain(alias);            if ((chain == null) || (chain.length == 0)) {                // must be secret key entry, ignore                continue;            }             boolean incompatible = false;            for (Certificate cert : chain) {                if (cert instanceof X509Certificate == false) {                    // not an X509Certificate, ignore this alias                    incompatible = true;                    break;                }            }            if (incompatible) {                continue;            }             // check keytype            int keyIndex = -1;            int j = 0;            for (KeyType keyType : keyTypes) {                if (keyType.matches(chain)) {                    keyIndex = j;                    break;                }                j++;            }            if (keyIndex == -1) {                if (useDebug) {                    debug.println("Ignoring alias " + alias                                + ": key algorithm does not match");                }                continue;            }            // check issuers            if (issuerSet != null) {                boolean found = false;                for (Certificate cert : chain) {                    X509Certificate xcert = (X509Certificate)cert;                    if (issuerSet.contains(xcert.getIssuerX500Principal())) {                        found = true;                        break;                    }                }                if (found == false) {                    if (useDebug) {                        debug.println("Ignoring alias " + alias                                    + ": issuers do not match");                    }                    continue;                }            }             // check the algorithm constraints            if (constraints != null &&                    !conformsToAlgorithmConstraints(constraints, chain)) {                 if (useDebug) {                    debug.println("Ignoring alias " + alias +                            ": certificate list does not conform to " +                            "algorithm constraints");                }                continue;            }             if (date == null) {                date = new Date();            }            CheckResult checkResult =                    checkType.check((X509Certificate)chain[0], date);            EntryStatus status =                    new EntryStatus(builderIndex, keyIndex,                                        alias, chain, checkResult);            if (!preferred && checkResult == CheckResult.OK && keyIndex == 0) {                preferred = true;            }            if (preferred && (findAll == false)) {                // if we have a good match and do not need all matches,                // return immediately                return Collections.singletonList(status);            } else {                if (results == null) {                    results = new ArrayList<EntryStatus>();                }                results.add(status);            }        }        return results;    }     private static boolean conformsToAlgorithmConstraints(            AlgorithmConstraints constraints, Certificate[] chain) {         AlgorithmChecker checker = new AlgorithmChecker(constraints);        try {            checker.init(false);        } catch (CertPathValidatorException cpve) {            // unlikely to happen            return false;        }         // It is a forward checker, so we need to check from trust to target.        for (int i = chain.length - 1; i >= 0; i--) {            Certificate cert = chain[i];            try {                // We don't care about the unresolved critical extensions.                checker.check(cert, Collections.<String>emptySet());            } catch (CertPathValidatorException cpve) {                return false;            }        }         return true;    } }

Lines 501–741 of 741. Previous lines