diff -r 4976d4999a76 -r 6fbaec35c792 jdk/src/share/classes/sun/security/validator/SimpleValidator.java --- a/jdk/src/share/classes/sun/security/validator/SimpleValidator.java Tue May 26 10:12:22 2009 +0800 +++ b/jdk/src/share/classes/sun/security/validator/SimpleValidator.java Tue May 26 16:19:18 2009 +0800 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2002-2009 Sun Microsystems, Inc. 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 @@ -129,6 +129,7 @@ } // verify top down, starting at the certificate issued by // the trust anchor + int maxPathLength = chain.length - 1; for (int i = chain.length - 2; i >= 0; i--) { X509Certificate issuerCert = chain[i + 1]; X509Certificate cert = chain[i]; @@ -157,14 +158,14 @@ // check extensions for CA certs if (i != 0) { - checkExtensions(cert, i); + maxPathLength = checkExtensions(cert, maxPathLength); } } return chain; } - private void checkExtensions(X509Certificate cert, int index) + private int checkExtensions(X509Certificate cert, int maxPathLen) throws CertificateException { Set critSet = cert.getCriticalExtensionOIDs(); if (critSet == null) { @@ -172,7 +173,8 @@ } // Check the basic constraints extension - checkBasicConstraints(cert, critSet, index); + int pathLenConstraint = + checkBasicConstraints(cert, critSet, maxPathLen); // Check the key usage and extended key usage extensions checkKeyUsage(cert, critSet); @@ -185,6 +187,8 @@ ("Certificate contains unknown critical extensions: " + critSet, ValidatorException.T_CA_EXTENSIONS, cert); } + + return pathLenConstraint; } private void checkNetscapeCertType(X509Certificate cert, @@ -246,8 +250,8 @@ } } - private void checkBasicConstraints(X509Certificate cert, - Set critSet, int index) throws CertificateException { + private int checkBasicConstraints(X509Certificate cert, + Set critSet, int maxPathLen) throws CertificateException { critSet.remove(OID_BASIC_CONSTRAINTS); int constraints = cert.getBasicConstraints(); @@ -256,10 +260,23 @@ throw new ValidatorException("End user tried to act as a CA", ValidatorException.T_CA_EXTENSIONS, cert); } - if (index - 1 > constraints) { - throw new ValidatorException("Violated path length constraints", - ValidatorException.T_CA_EXTENSIONS, cert); + + // if the certificate is self-issued, ignore the pathLenConstraint + // checking. + if (!X509CertImpl.isSelfIssued(cert)) { + if (maxPathLen <= 1) { // reserved one for end-entity certificate + throw new ValidatorException("Violated path length constraints", + ValidatorException.T_CA_EXTENSIONS, cert); + } + + maxPathLen--; } + + if (maxPathLen > constraints) { + maxPathLen = constraints; + } + + return maxPathLen; } /* @@ -304,18 +321,18 @@ } c.add(cert); } + // check if we can append a trusted cert X509Certificate cert = chain[chain.length - 1]; X500Principal subject = cert.getSubjectX500Principal(); X500Principal issuer = cert.getIssuerX500Principal(); - if (subject.equals(issuer) == false) { - List list = trustedX500Principals.get(issuer); - if (list != null) { - X509Certificate trustedCert = list.iterator().next(); - c.add(trustedCert); - return c.toArray(CHAIN0); - } + List list = trustedX500Principals.get(issuer); + if (list != null) { + X509Certificate trustedCert = list.iterator().next(); + c.add(trustedCert); + return c.toArray(CHAIN0); } + // no trusted cert found, error throw new ValidatorException(ValidatorException.T_NO_TRUST_ANCHOR); }