提交 03612b02 编写于 作者: M mullan

6854712: Revocation checking enhancements (JEP-124)

6637288: Add OCSP support to PKIX CertPathBuilder implementation
7126011: ReverseBuilder.getMatchingCACerts may throws NPE
Reviewed-by: xuelei
上级 f0352f09
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -45,15 +45,28 @@ import sun.security.jca.GetInstance.Instance; ...@@ -45,15 +45,28 @@ import sun.security.jca.GetInstance.Instance;
* one of the static <code>getInstance</code> methods, passing in the * one of the static <code>getInstance</code> methods, passing in the
* algorithm name of the <code>CertPathBuilder</code> desired and optionally * algorithm name of the <code>CertPathBuilder</code> desired and optionally
* the name of the provider desired. * the name of the provider desired.
* <p> *
* Once a <code>CertPathBuilder</code> object has been created, certification * <p>Once a <code>CertPathBuilder</code> object has been created, certification
* paths can be constructed by calling the {@link #build build} method and * paths can be constructed by calling the {@link #build build} method and
* passing it an algorithm-specific set of parameters. If successful, the * passing it an algorithm-specific set of parameters. If successful, the
* result (including the <code>CertPath</code> that was built) is returned * result (including the <code>CertPath</code> that was built) is returned
* in an object that implements the <code>CertPathBuilderResult</code> * in an object that implements the <code>CertPathBuilderResult</code>
* interface. * interface.
* *
* <p> Every implementation of the Java platform is required to support the * <p>The {@link #getRevocationChecker} method allows an application to specify
* additional algorithm-specific parameters and options used by the
* {@code CertPathBuilder} when checking the revocation status of certificates.
* Here is an example demonstrating how it is used with the PKIX algorithm:
*
* <pre>
* CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
* PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
* rc.setOptions(EnumSet.of(Option.PREFER_CRLS));
* params.addCertPathChecker(rc);
* CertPathBuilderResult cpbr = cpb.build(params);
* </pre>
*
* <p>Every implementation of the Java platform is required to support the
* following standard <code>CertPathBuilder</code> algorithm: * following standard <code>CertPathBuilder</code> algorithm:
* <ul> * <ul>
* <li><tt>PKIX</tt></li> * <li><tt>PKIX</tt></li>
...@@ -96,10 +109,9 @@ public class CertPathBuilder { ...@@ -96,10 +109,9 @@ public class CertPathBuilder {
* </pre> * </pre>
*/ */
private static final String CPB_TYPE = "certpathbuilder.type"; private static final String CPB_TYPE = "certpathbuilder.type";
private static final Debug debug = Debug.getInstance("certpath"); private final CertPathBuilderSpi builderSpi;
private CertPathBuilderSpi builderSpi; private final Provider provider;
private Provider provider; private final String algorithm;
private String algorithm;
/** /**
* Creates a <code>CertPathBuilder</code> object of the given algorithm, * Creates a <code>CertPathBuilder</code> object of the given algorithm,
...@@ -290,15 +302,30 @@ public class CertPathBuilder { ...@@ -290,15 +302,30 @@ public class CertPathBuilder {
* if no such property exists. * if no such property exists.
*/ */
public final static String getDefaultType() { public final static String getDefaultType() {
String cpbtype; String cpbtype =
cpbtype = AccessController.doPrivileged(new PrivilegedAction<String>() { AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() { public String run() {
return Security.getProperty(CPB_TYPE); return Security.getProperty(CPB_TYPE);
} }
}); });
if (cpbtype == null) { return (cpbtype == null) ? "PKIX" : cpbtype;
cpbtype = "PKIX"; }
}
return cpbtype; /**
* Returns a {@code CertPathChecker} that the encapsulated
* {@code CertPathBuilderSpi} implementation uses to check the revocation
* status of certificates. A PKIX implementation returns objects of
* type {@code PKIXRevocationChecker}.
*
* <p>The primary purpose of this method is to allow callers to specify
* additional input parameters and options specific to revocation checking.
* See the class description for an example.
*
* @throws UnsupportedOperationException if the service provider does not
* support this method
* @since 1.8
*/
public final CertPathChecker getRevocationChecker() {
return builderSpi.engineGetRevocationChecker();
} }
} }
/* /*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -72,4 +72,25 @@ public abstract class CertPathBuilderSpi { ...@@ -72,4 +72,25 @@ public abstract class CertPathBuilderSpi {
*/ */
public abstract CertPathBuilderResult engineBuild(CertPathParameters params) public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
throws CertPathBuilderException, InvalidAlgorithmParameterException; throws CertPathBuilderException, InvalidAlgorithmParameterException;
/**
* Returns a {@code CertPathChecker} that this implementation uses to
* check the revocation status of certificates. A PKIX implementation
* returns objects of type {@code PKIXRevocationChecker}.
*
* <p>The primary purpose of this method is to allow callers to specify
* additional input parameters and options specific to revocation checking.
* See the class description of {@code CertPathBuilder} for an example.
*
* <p>This method was added to version 1.8 of the Java Platform Standard
* Edition. In order to maintain backwards compatibility with existing
* service providers, this method cannot be abstract and by default throws
* an {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException if this method is not supported
* @since 1.8
*/
public CertPathChecker engineGetRevocationChecker() {
throw new UnsupportedOperationException();
}
} }
/*
* Copyright (c) 2012, 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 java.security.cert;
/**
* <p>Performs one or more checks on each {@code Certificate} of a
* {@code CertPath}.
*
* <p>A {@code CertPathChecker} implementation is typically created to extend
* a certification path validation algorithm. For example, an implementation
* may check for and process a critical private extension of each certificate
* in a certification path.
*
* @since 1.8
*/
public interface CertPathChecker {
/**
* Initializes the internal state of this {@code CertPathChecker}.
*
* <p>The {@code forward} flag specifies the order that certificates will
* be passed to the {@link #check check} method (forward or reverse).
*
* @param forward the order that certificates are presented to the
* {@code check} method. If {@code true}, certificates are
* presented from target to trust anchor (forward); if
* {@code false}, from trust anchor to target (reverse).
* @throws CertPathValidatorException if this {@code CertPathChecker} is
* unable to check certificates in the specified order
*/
void init(boolean forward) throws CertPathValidatorException;
/**
* Indicates if forward checking is supported. Forward checking refers
* to the ability of the {@code CertPathChecker} to perform its checks
* when certificates are presented to the {@code check} method in the
* forward direction (from target to trust anchor).
*
* @return {@code true} if forward checking is supported, {@code false}
* otherwise
*/
boolean isForwardCheckingSupported();
/**
* Performs the check(s) on the specified certificate using its internal
* state. The certificates are presented in the order specified by the
* {@code init} method.
*
* @param cert the {@code Certificate} to be checked
* @throws CertPathValidatorException if the specified certificate does
* not pass the check
*/
void check(Certificate cert) throws CertPathValidatorException;
}
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -46,15 +46,29 @@ import sun.security.jca.GetInstance.Instance; ...@@ -46,15 +46,29 @@ import sun.security.jca.GetInstance.Instance;
* call one of the static <code>getInstance</code> methods, passing in the * call one of the static <code>getInstance</code> methods, passing in the
* algorithm name of the <code>CertPathValidator</code> desired and * algorithm name of the <code>CertPathValidator</code> desired and
* optionally the name of the provider desired. * optionally the name of the provider desired.
* <p> *
* Once a <code>CertPathValidator</code> object has been created, it can * <p>Once a <code>CertPathValidator</code> object has been created, it can
* be used to validate certification paths by calling the {@link #validate * be used to validate certification paths by calling the {@link #validate
* validate} method and passing it the <code>CertPath</code> to be validated * validate} method and passing it the <code>CertPath</code> to be validated
* and an algorithm-specific set of parameters. If successful, the result is * and an algorithm-specific set of parameters. If successful, the result is
* returned in an object that implements the * returned in an object that implements the
* <code>CertPathValidatorResult</code> interface. * <code>CertPathValidatorResult</code> interface.
* *
* <p> Every implementation of the Java platform is required to support the * <p>The {@link #getRevocationChecker} method allows an application to specify
* additional algorithm-specific parameters and options used by the
* {@code CertPathValidator} when checking the revocation status of
* certificates. Here is an example demonstrating how it is used with the PKIX
* algorithm:
*
* <pre>
* CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
* PKIXRevocationChecker rc = (PKIXRevocationChecker)cpv.getRevocationChecker();
* rc.setOptions(EnumSet.of(Option.SOFT_FAIL));
* params.addCertPathChecker(rc);
* CertPathValidatorResult cpvr = cpv.validate(path, params);
* </pre>
*
* <p>Every implementation of the Java platform is required to support the
* following standard <code>CertPathValidator</code> algorithm: * following standard <code>CertPathValidator</code> algorithm:
* <ul> * <ul>
* <li><tt>PKIX</tt></li> * <li><tt>PKIX</tt></li>
...@@ -96,10 +110,9 @@ public class CertPathValidator { ...@@ -96,10 +110,9 @@ public class CertPathValidator {
* </pre> * </pre>
*/ */
private static final String CPV_TYPE = "certpathvalidator.type"; private static final String CPV_TYPE = "certpathvalidator.type";
private static final Debug debug = Debug.getInstance("certpath"); private final CertPathValidatorSpi validatorSpi;
private CertPathValidatorSpi validatorSpi; private final Provider provider;
private Provider provider; private final String algorithm;
private String algorithm;
/** /**
* Creates a <code>CertPathValidator</code> object of the given algorithm, * Creates a <code>CertPathValidator</code> object of the given algorithm,
...@@ -301,15 +314,30 @@ public class CertPathValidator { ...@@ -301,15 +314,30 @@ public class CertPathValidator {
* if no such property exists. * if no such property exists.
*/ */
public final static String getDefaultType() { public final static String getDefaultType() {
String cpvtype; String cpvtype =
cpvtype = AccessController.doPrivileged(new PrivilegedAction<String>() { AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() { public String run() {
return Security.getProperty(CPV_TYPE); return Security.getProperty(CPV_TYPE);
} }
}); });
if (cpvtype == null) { return (cpvtype == null) ? "PKIX" : cpvtype;
cpvtype = "PKIX"; }
}
return cpvtype; /**
* Returns a {@code CertPathChecker} that the encapsulated
* {@code CertPathValidatorSpi} implementation uses to check the revocation
* status of certificates. A PKIX implementation returns objects of
* type {@code PKIXRevocationChecker}.
*
* <p>The primary purpose of this method is to allow callers to specify
* additional input parameters and options specific to revocation checking.
* See the class description for an example.
*
* @throws UnsupportedOperationException if the service provider does not
* support this method
* @since 1.8
*/
public final CertPathChecker getRevocationChecker() {
return validatorSpi.engineGetRevocationChecker();
} }
} }
/* /*
* Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -82,4 +82,25 @@ public abstract class CertPathValidatorSpi { ...@@ -82,4 +82,25 @@ public abstract class CertPathValidatorSpi {
public abstract CertPathValidatorResult public abstract CertPathValidatorResult
engineValidate(CertPath certPath, CertPathParameters params) engineValidate(CertPath certPath, CertPathParameters params)
throws CertPathValidatorException, InvalidAlgorithmParameterException; throws CertPathValidatorException, InvalidAlgorithmParameterException;
/**
* Returns a {@code CertPathChecker} that this implementation uses to
* check the revocation status of certificates. A PKIX implementation
* returns objects of type {@code PKIXRevocationChecker}.
*
* <p>The primary purpose of this method is to allow callers to specify
* additional input parameters and options specific to revocation checking.
* See the class description of {@code CertPathValidator} for an example.
*
* <p>This method was added to version 1.8 of the Java Platform Standard
* Edition. In order to maintain backwards compatibility with existing
* service providers, this method cannot be abstract and by default throws
* an {@code UnsupportedOperationException}.
*
* @throws UnsupportedOperationException if this method is not supported
* @since 1.8
*/
public CertPathChecker engineGetRevocationChecker() {
throw new UnsupportedOperationException();
}
} }
/* /*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -87,7 +87,8 @@ import java.util.Set; ...@@ -87,7 +87,8 @@ import java.util.Set;
* @author Yassir Elley * @author Yassir Elley
* @author Sean Mullan * @author Sean Mullan
*/ */
public abstract class PKIXCertPathChecker implements Cloneable { public abstract class PKIXCertPathChecker
implements CertPathChecker, Cloneable {
/** /**
* Default constructor. * Default constructor.
...@@ -111,6 +112,7 @@ public abstract class PKIXCertPathChecker implements Cloneable { ...@@ -111,6 +112,7 @@ public abstract class PKIXCertPathChecker implements Cloneable {
* the specified order; it should never be thrown if the forward flag * the specified order; it should never be thrown if the forward flag
* is false since reverse checking must be supported * is false since reverse checking must be supported
*/ */
@Override
public abstract void init(boolean forward) public abstract void init(boolean forward)
throws CertPathValidatorException; throws CertPathValidatorException;
...@@ -123,6 +125,7 @@ public abstract class PKIXCertPathChecker implements Cloneable { ...@@ -123,6 +125,7 @@ public abstract class PKIXCertPathChecker implements Cloneable {
* @return <code>true</code> if forward checking is supported, * @return <code>true</code> if forward checking is supported,
* <code>false</code> otherwise * <code>false</code> otherwise
*/ */
@Override
public abstract boolean isForwardCheckingSupported(); public abstract boolean isForwardCheckingSupported();
/** /**
...@@ -162,6 +165,17 @@ public abstract class PKIXCertPathChecker implements Cloneable { ...@@ -162,6 +165,17 @@ public abstract class PKIXCertPathChecker implements Cloneable {
Collection<String> unresolvedCritExts) Collection<String> unresolvedCritExts)
throws CertPathValidatorException; throws CertPathValidatorException;
/**
* {@inheritDoc}
*
* <p>This implementation calls
* {@code check(cert, java.util.Collections.<String>emptySet())}.
*/
@Override
public void check(Certificate cert) throws CertPathValidatorException {
check(cert, java.util.Collections.<String>emptySet());
}
/** /**
* Returns a clone of this object. Calls the <code>Object.clone()</code> * Returns a clone of this object. Calls the <code>Object.clone()</code>
* method. * method.
...@@ -170,6 +184,7 @@ public abstract class PKIXCertPathChecker implements Cloneable { ...@@ -170,6 +184,7 @@ public abstract class PKIXCertPathChecker implements Cloneable {
* *
* @return a copy of this <code>PKIXCertPathChecker</code> * @return a copy of this <code>PKIXCertPathChecker</code>
*/ */
@Override
public Object clone() { public Object clone() {
try { try {
return super.clone(); return super.clone();
......
/*
* Copyright (c) 2012, 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 java.security.cert;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* A {@code PKIXCertPathChecker} for checking the revocation status of
* certificates with the PKIX algorithm.
*
* <p>A {@code PKIXRevocationChecker} checks the revocation status of
* certificates with the Online Certificate Status Protocol (OCSP) or
* Certificate Revocation Lists (CRLs). OCSP is described in RFC 2560 and
* is a network protocol for determining the status of a certificate. A CRL
* is a time-stamped list identifying revoked certificates, and RFC 5280
* describes an algorithm for determining the revocation status of certificates
* using CRLs.
*
* <p>Each {@code PKIXRevocationChecker} must be able to check the revocation
* status of certificates with OCSP and CRLs. By default, OCSP is the
* preferred mechanism for checking revocation status, with CRLs as the
* fallback mechanism. However, this preference can be switched to CRLs with
* the {@link Option.PREFER_CRLS} option.
*
* <p>A {@code PKIXRevocationChecker} is obtained by calling the
* {@link CertPathValidator#getRevocationChecker getRevocationChecker} method
* of a PKIX {@code CertPathValidator}. Additional parameters and options
* specific to revocation can be set (by calling {@link #setOCSPResponder}
* method for instance). The {@code PKIXRevocationChecker} is added to
* a {@code PKIXParameters} object using the
* {@link PKIXParameters#addCertPathChecker addCertPathChecker}
* or {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} method,
* and then the {@code PKIXParameters} is passed along with the {@code CertPath}
* to be validated to the {@link CertPathValidator#validate validate} method
* of a PKIX {@code CertPathValidator}. When supplying a revocation checker in
* this manner, do not enable the default revocation checking mechanism (by
* calling {@link PKIXParameters#setRevocationEnabled}.
*
* <p>Note that when a {@code PKIXRevocationChecker} is added to
* {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker};
* thus any subsequent modifications to the {@code PKIXRevocationChecker}
* have no effect.
*
* <p>Any parameter that is not set (or is set to {@code null}) will be set to
* the default value for that parameter.
*
* <p><b>Concurrent Access</b>
*
* <p>Unless otherwise specified, the methods defined in this class are not
* thread-safe. Multiple threads that need to access a single object
* concurrently should synchronize amongst themselves and provide the
* necessary locking. Multiple threads each manipulating separate objects
* need not synchronize.
*
* @since 1.8
*/
public abstract class PKIXRevocationChecker extends PKIXCertPathChecker {
private URI ocspResponder;
private X509Certificate ocspResponderCert;
private List<Extension> ocspExtensions = Collections.<Extension>emptyList();
private Map<X509Certificate, byte[]> ocspStapled = Collections.emptyMap();
private Set<Option> options = Collections.emptySet();
protected PKIXRevocationChecker() {}
/**
* Sets the URI that identifies the location of the OCSP responder. This
* overrides the {@code ocsp.responderURL} security property and any
* responder specified in a certificate's Authority Information Access
* Extension, as defined in RFC 5280.
*
* @param uri the responder URI
*/
public void setOCSPResponder(URI uri) {
this.ocspResponder = uri;
}
/**
* Gets the URI that identifies the location of the OCSP responder. This
* overrides the {@code ocsp.responderURL} security property. If this
* parameter or the {@code ocsp.responderURL} property is not set, the
* location is determined from the certificate's Authority Information
* Access Extension, as defined in RFC 5280.
*
* @return the responder URI, or {@code null} if not set
*/
public URI getOCSPResponder() {
return ocspResponder;
}
/**
* Sets the OCSP responder's certificate. This overrides the
* {@code ocsp.responderCertSubjectName},
* {@code ocsp.responderCertIssuerName},
* and {@code ocsp.responderCertSerialNumber} security properties.
*
* @param cert the responder's certificate
*/
public void setOCSPResponderCert(X509Certificate cert) {
this.ocspResponderCert = cert;
}
/**
* Gets the OCSP responder's certificate. This overrides the
* {@code ocsp.responderCertSubjectName},
* {@code ocsp.responderCertIssuerName},
* and {@code ocsp.responderCertSerialNumber} security properties. If this
* parameter or the aforementioned properties are not set, then the
* responder's certificate is determined as specified in RFC 2560.
*
* @return the responder's certificate, or {@code null} if not set
*/
public X509Certificate getOCSPResponderCert() {
return ocspResponderCert;
}
// request extensions; single extensions not supported
/**
* Sets the optional OCSP request extensions.
*
* @param extensions a list of extensions. The list is copied to protect
* against subsequent modification.
*/
public void setOCSPExtensions(List<Extension> extensions)
{
this.ocspExtensions = (extensions == null)
? Collections.<Extension>emptyList()
: new ArrayList<Extension>(extensions);
}
/**
* Gets the optional OCSP request extensions.
*
* @return an unmodifiable list of extensions. Returns an empty list if no
* extensions have been specified.
*/
public List<Extension> getOCSPExtensions() {
return Collections.unmodifiableList(ocspExtensions);
}
/**
* Sets the stapled OCSP responses. These responses are used to determine
* the revocation status of the specified certificates when OCSP is used.
*
* @param responses a map of stapled OCSP responses. Each key is an
* {@code X509Certificate} that maps to the corresponding
* DER-encoded OCSP response for that certificate. A deep copy of
* the map is performed to protect against subsequent modification.
*/
public void setOCSPStapledResponses(Map<X509Certificate, byte[]> responses)
{
if (responses == null) {
this.ocspStapled = Collections.<X509Certificate, byte[]>emptyMap();
} else {
Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
copy.put(e.getKey(), e.getValue().clone());
}
this.ocspStapled = copy;
}
}
/**
* Gets the stapled OCSP responses. These responses are used to determine
* the revocation status of the specified certificates when OCSP is used.
*
* @return a map of stapled OCSP responses. Each key is an
* {@code X509Certificate} that maps to the corresponding
* DER-encoded OCSP response for that certificate. A deep copy of
* the map is returned to protect against subsequent modification.
* Returns an empty map if no responses have been specified.
*/
public Map<X509Certificate, byte[]> getOCSPStapledResponses() {
Map<X509Certificate, byte[]> copy = new HashMap<>(ocspStapled.size());
for (Map.Entry<X509Certificate, byte[]> e : ocspStapled.entrySet()) {
copy.put(e.getKey(), e.getValue().clone());
}
return copy;
}
/**
* Sets the revocation options.
*
* @param options a set of revocation options. The set is copied to protect
* against subsequent modification.
*/
public void setOptions(Set<Option> options) {
this.options = (options == null)
? Collections.<Option>emptySet()
: new HashSet<Option>(options);
}
/**
* Gets the revocation options.
*
* @return an unmodifiable set of revocation options, or an empty set if
* none are specified
*/
public Set<Option> getOptions() {
return Collections.unmodifiableSet(options);
}
@Override
public Object clone() {
PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone();
copy.ocspExtensions = new ArrayList<>(ocspExtensions);
copy.ocspStapled = new HashMap<>(ocspStapled);
// deep-copy the encoded stapled responses, since they are mutable
for (Map.Entry<X509Certificate, byte[]> entry :
copy.ocspStapled.entrySet())
{
byte[] encoded = entry.getValue();
entry.setValue(encoded.clone());
}
copy.options = new HashSet<>(options);
return copy;
}
/**
* Various revocation options that can be specified for the revocation
* checking mechanism.
*/
public enum Option {
/**
* Only check the revocation status of end-entity certificates.
*/
ONLY_END_ENTITY,
/**
* Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each
* PKIX implementation should document further details of their
* specific preference rules and fallback policies.
*/
PREFER_CRLS,
/**
* Ignore network failures. The default behavior is to consider it a
* failure if the revocation status of a certificate cannot be obtained
* due to a network error. This option applies to both OCSP and CRLs.
*/
SOFT_FAIL
}
}
<!-- <!--
Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it This code is free software; you can redistribute it and/or modify it
...@@ -38,8 +38,10 @@ certificates and X.509 v2 CRLs. ...@@ -38,8 +38,10 @@ certificates and X.509 v2 CRLs.
<li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html"> <li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
Cryptography Architecture (JCA) Reference Guide</b></a> Cryptography Architecture (JCA) Reference Guide</b></a>
<li>RFC 3280: Internet X.509 Public Key Infrastructure Certificate and <li>RFC 5280: Internet X.509 Public Key Infrastructure Certificate and
Certificate Revocation List (CRL) Profile Certificate Revocation List (CRL) Profile
<li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate
Status Protocol - OCSP
<li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html"> <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
Cryptography Architecture Standard Algorithm Name Cryptography Architecture Standard Algorithm Name
...@@ -50,8 +52,8 @@ certificates and X.509 v2 CRLs. ...@@ -50,8 +52,8 @@ certificates and X.509 v2 CRLs.
For information about X.509 certificates and CRLs, please see: For information about X.509 certificates and CRLs, please see:
<ul> <ul>
<li><a href="http://www.ietf.org/rfc/rfc3280.txt"> <li><a href="http://www.ietf.org/rfc/rfc5280.txt">
http://www.ietf.org/rfc/rfc3280.txt</a> http://www.ietf.org/rfc/rfc5280.txt</a>
<li><a href= <li><a href=
"{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html"> "{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT> <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
......
/* /*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -24,13 +24,11 @@ ...@@ -24,13 +24,11 @@
*/ */
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
/** /**
* An AdjacencyList is used to store the history of certification paths * An AdjacencyList is used to store the history of certification paths
* attempted in constructing a path from an initiator to a target. The * attempted in constructing a path from an initiator to a target. The
...@@ -123,124 +121,117 @@ public class AdjacencyList { ...@@ -123,124 +121,117 @@ public class AdjacencyList {
* at the start. * at the start.
*/ */
private boolean buildList(List<List<Vertex>> theList, int index, private boolean buildList(List<List<Vertex>> theList, int index,
BuildStep follow) { BuildStep follow) {
// Each time this method is called, we're examining a new list // Each time this method is called, we're examining a new list
// from the global list. So, we have to start by getting the list // from the global list. So, we have to start by getting the list
// that contains the set of Vertexes we're considering. // that contains the set of Vertexes we're considering.
List<Vertex> l = theList.get(index); List<Vertex> l = theList.get(index);
try { // we're interested in the case where all indexes are -1...
// we're interested in the case where all indexes are -1... boolean allNegOne = true;
boolean allNegOne = true; // ...and in the case where every entry has a Throwable
// ...and in the case where every entry has a Throwable boolean allXcps = true;
boolean allXcps = true;
for (Vertex v : l) { for (Vertex v : l) {
if (v.getIndex() != -1) { if (v.getIndex() != -1) {
// count an empty list the same as an index of -1...this // count an empty list the same as an index of -1...this
// is to patch a bug somewhere in the builder // is to patch a bug somewhere in the builder
if (theList.get(v.getIndex()).size() != 0) if (theList.get(v.getIndex()).size() != 0)
allNegOne = false; allNegOne = false;
} } else {
else if (v.getThrowable() == null)
if (v.getThrowable() == null) allXcps = false;
allXcps = false;
// every entry, regardless of the final use for it, is always
// entered as a possible step before we take any actions
mStepList.add(new BuildStep(v, BuildStep.POSSIBLE));
} }
// every entry, regardless of the final use for it, is always
// entered as a possible step before we take any actions
mStepList.add(new BuildStep(v, BuildStep.POSSIBLE));
}
if (allNegOne) { if (allNegOne) {
// There are two cases that we could be looking at here. We // There are two cases that we could be looking at here. We
// may need to back up, or the build may have succeeded at // may need to back up, or the build may have succeeded at
// this point. This is based on whether or not any // this point. This is based on whether or not any
// exceptions were found in the list. // exceptions were found in the list.
if (allXcps) { if (allXcps) {
// we need to go back...see if this is the last one // we need to go back...see if this is the last one
if (follow == null) if (follow == null)
mStepList.add(new BuildStep(null, BuildStep.FAIL)); mStepList.add(new BuildStep(null, BuildStep.FAIL));
else else
mStepList.add(new BuildStep(follow.getVertex(), mStepList.add(new BuildStep(follow.getVertex(),
BuildStep.BACK)); BuildStep.BACK));
return false;
} else {
// we succeeded...now the only question is which is the
// successful step? If there's only one entry without
// a throwable, then that's the successful step. Otherwise,
// we'll have to make some guesses...
List<Vertex> possibles = new ArrayList<Vertex>();
for (Vertex v : l) {
if (v.getThrowable() == null)
possibles.add(v);
}
if (possibles.size() == 1) { return false;
// real easy...we've found the final Vertex } else {
mStepList.add(new BuildStep(possibles.get(0), // we succeeded...now the only question is which is the
BuildStep.SUCCEED)); // successful step? If there's only one entry without
} else { // a throwable, then that's the successful step. Otherwise,
// ok...at this point, there is more than one Cert // we'll have to make some guesses...
// which might be the succeed step...how do we know List<Vertex> possibles = new ArrayList<>();
// which it is? I'm going to assume that our builder for (Vertex v : l) {
// algorithm is good enough to know which is the if (v.getThrowable() == null)
// correct one, and put it first...but a FIXME goes possibles.add(v);
// here anyway, and we should be comparing to the }
// target/initiator Cert...
mStepList.add(new BuildStep(possibles.get(0),
BuildStep.SUCCEED));
}
return true; if (possibles.size() == 1) {
// real easy...we've found the final Vertex
mStepList.add(new BuildStep(possibles.get(0),
BuildStep.SUCCEED));
} else {
// ok...at this point, there is more than one Cert
// which might be the succeed step...how do we know
// which it is? I'm going to assume that our builder
// algorithm is good enough to know which is the
// correct one, and put it first...but a FIXME goes
// here anyway, and we should be comparing to the
// target/initiator Cert...
mStepList.add(new BuildStep(possibles.get(0),
BuildStep.SUCCEED));
} }
} else {
// There's at least one thing that we can try before we give
// up and go back. Run through the list now, and enter a new
// BuildStep for each path that we try to follow. If none of
// the paths we try produce a successful end, we're going to
// have to back out ourselves.
boolean success = false;
for (Vertex v : l) { return true;
}
} else {
// There's at least one thing that we can try before we give
// up and go back. Run through the list now, and enter a new
// BuildStep for each path that we try to follow. If none of
// the paths we try produce a successful end, we're going to
// have to back out ourselves.
boolean success = false;
for (Vertex v : l) {
// Note that we'll only find a SUCCEED case when we're // Note that we'll only find a SUCCEED case when we're
// looking at the last possible path, so we don't need to // looking at the last possible path, so we don't need to
// consider success in the while loop // consider success in the while loop
if (v.getIndex() != -1) { if (v.getIndex() != -1) {
if (theList.get(v.getIndex()).size() != 0) { if (theList.get(v.getIndex()).size() != 0) {
// If the entry we're looking at doesn't have an // If the entry we're looking at doesn't have an
// index of -1, and doesn't lead to an empty list, // index of -1, and doesn't lead to an empty list,
// then it's something we follow! // then it's something we follow!
BuildStep bs = new BuildStep(v, BuildStep.FOLLOW); BuildStep bs = new BuildStep(v, BuildStep.FOLLOW);
mStepList.add(bs); mStepList.add(bs);
success = buildList(theList, v.getIndex(), bs); success = buildList(theList, v.getIndex(), bs);
}
} }
} }
}
if (success) { if (success) {
// We're already finished! // We're already finished!
return true; return true;
} else { } else {
// We failed, and we've exhausted all the paths that we // We failed, and we've exhausted all the paths that we
// could take. The only choice is to back ourselves out. // could take. The only choice is to back ourselves out.
if (follow == null) if (follow == null)
mStepList.add(new BuildStep(null, BuildStep.FAIL)); mStepList.add(new BuildStep(null, BuildStep.FAIL));
else else
mStepList.add(new BuildStep(follow.getVertex(), mStepList.add(new BuildStep(follow.getVertex(),
BuildStep.BACK)); BuildStep.BACK));
return false; return false;
}
} }
} }
catch (Exception e) {}
// we'll never get here, but you know java...
return false;
} }
/** /**
...@@ -248,23 +239,20 @@ public class AdjacencyList { ...@@ -248,23 +239,20 @@ public class AdjacencyList {
* *
* @return String representation * @return String representation
*/ */
@Override
public String toString() { public String toString() {
String out = "[\n"; StringBuilder sb = new StringBuilder("[\n");
int i = 0; int i = 0;
for (List<Vertex> l : mOrigList) { for (List<Vertex> l : mOrigList) {
out = out + "LinkedList[" + i++ + "]:\n"; sb.append("LinkedList[").append(i++).append("]:\n");
for (Vertex step : l) { for (Vertex step : l) {
try { sb.append(step.toString()).append("\n");
out = out + step.toString();
out = out + "\n";
}
catch (Exception e) { out = out + "No Such Element\n"; }
} }
} }
out = out + "]\n"; sb.append("]\n");
return out; return sb.toString();
} }
} }
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -62,7 +62,7 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -62,7 +62,7 @@ class BasicChecker extends PKIXCertPathChecker {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private final PublicKey trustedPubKey; private final PublicKey trustedPubKey;
private final X500Principal caName; private final X500Principal caName;
private final Date testDate; private final Date date;
private final String sigProvider; private final String sigProvider;
private final boolean sigOnly; private final boolean sigOnly;
private X500Principal prevSubject; private X500Principal prevSubject;
...@@ -73,14 +73,13 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -73,14 +73,13 @@ class BasicChecker extends PKIXCertPathChecker {
* *
* @param anchor the anchor selected to validate the target certificate * @param anchor the anchor selected to validate the target certificate
* @param testDate the time for which the validity of the certificate * @param testDate the time for which the validity of the certificate
* should be determined * should be determined
* @param sigProvider the name of the signature provider * @param sigProvider the name of the signature provider
* @param sigOnly true if only signature checking is to be done; * @param sigOnly true if only signature checking is to be done;
* if false, all checks are done * if false, all checks are done
*/ */
BasicChecker(TrustAnchor anchor, Date testDate, String sigProvider, BasicChecker(TrustAnchor anchor, Date date, String sigProvider,
boolean sigOnly) throws CertPathValidatorException boolean sigOnly) {
{
if (anchor.getTrustedCert() != null) { if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey(); this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
this.caName = anchor.getTrustedCert().getSubjectX500Principal(); this.caName = anchor.getTrustedCert().getSubjectX500Principal();
...@@ -88,16 +87,16 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -88,16 +87,16 @@ class BasicChecker extends PKIXCertPathChecker {
this.trustedPubKey = anchor.getCAPublicKey(); this.trustedPubKey = anchor.getCAPublicKey();
this.caName = anchor.getCA(); this.caName = anchor.getCA();
} }
this.testDate = testDate; this.date = date;
this.sigProvider = sigProvider; this.sigProvider = sigProvider;
this.sigOnly = sigOnly; this.sigOnly = sigOnly;
init(false);
} }
/** /**
* Initializes the internal state of the checker from parameters * Initializes the internal state of the checker from parameters
* specified in the constructor. * specified in the constructor.
*/ */
@Override
public void init(boolean forward) throws CertPathValidatorException { public void init(boolean forward) throws CertPathValidatorException {
if (!forward) { if (!forward) {
prevPubKey = trustedPubKey; prevPubKey = trustedPubKey;
...@@ -108,10 +107,12 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -108,10 +107,12 @@ class BasicChecker extends PKIXCertPathChecker {
} }
} }
@Override
public boolean isForwardCheckingSupported() { public boolean isForwardCheckingSupported() {
return false; return false;
} }
@Override
public Set<String> getSupportedExtensions() { public Set<String> getSupportedExtensions() {
return null; return null;
} }
...@@ -124,33 +125,31 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -124,33 +125,31 @@ class BasicChecker extends PKIXCertPathChecker {
* @param cert the Certificate * @param cert the Certificate
* @param unresolvedCritExts a Collection of the unresolved critical * @param unresolvedCritExts a Collection of the unresolved critical
* extensions * extensions
* @exception CertPathValidatorException Exception thrown if certificate * @throws CertPathValidatorException if certificate does not verify
* does not verify.
*/ */
@Override
public void check(Certificate cert, Collection<String> unresolvedCritExts) public void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException throws CertPathValidatorException
{ {
X509Certificate currCert = (X509Certificate) cert; X509Certificate currCert = (X509Certificate)cert;
if (!sigOnly) { if (!sigOnly) {
verifyTimestamp(currCert, testDate); verifyTimestamp(currCert);
verifyNameChaining(currCert, prevSubject); verifyNameChaining(currCert);
} }
verifySignature(currCert, prevPubKey, sigProvider); verifySignature(currCert);
updateState(currCert); updateState(currCert);
} }
/** /**
* Verifies the signature on the certificate using the previous public key * Verifies the signature on the certificate using the previous public key.
* @param cert the Certificate *
* @param prevPubKey the previous PublicKey * @param cert the X509Certificate
* @param sigProvider a String containing the signature provider * @throws CertPathValidatorException if certificate does not verify
* @exception CertPathValidatorException Exception thrown if certificate
* does not verify.
*/ */
private void verifySignature(X509Certificate cert, PublicKey prevPubKey, private void verifySignature(X509Certificate cert)
String sigProvider) throws CertPathValidatorException throws CertPathValidatorException
{ {
String msg = "signature"; String msg = "signature";
if (debug != null) if (debug != null)
...@@ -162,7 +161,7 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -162,7 +161,7 @@ class BasicChecker extends PKIXCertPathChecker {
throw new CertPathValidatorException throw new CertPathValidatorException
(msg + " check failed", e, null, -1, (msg + " check failed", e, null, -1,
BasicReason.INVALID_SIGNATURE); BasicReason.INVALID_SIGNATURE);
} catch (Exception e) { } catch (GeneralSecurityException e) {
throw new CertPathValidatorException(msg + " check failed", e); throw new CertPathValidatorException(msg + " check failed", e);
} }
...@@ -173,7 +172,7 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -173,7 +172,7 @@ class BasicChecker extends PKIXCertPathChecker {
/** /**
* Internal method to verify the timestamp on a certificate * Internal method to verify the timestamp on a certificate
*/ */
private void verifyTimestamp(X509Certificate cert, Date date) private void verifyTimestamp(X509Certificate cert)
throws CertPathValidatorException throws CertPathValidatorException
{ {
String msg = "timestamp"; String msg = "timestamp";
...@@ -197,8 +196,8 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -197,8 +196,8 @@ class BasicChecker extends PKIXCertPathChecker {
/** /**
* Internal method to check that cert has a valid DN to be next in a chain * Internal method to check that cert has a valid DN to be next in a chain
*/ */
private void verifyNameChaining(X509Certificate cert, private void verifyNameChaining(X509Certificate cert)
X500Principal prevSubject) throws CertPathValidatorException throws CertPathValidatorException
{ {
if (prevSubject != null) { if (prevSubject != null) {
...@@ -207,8 +206,8 @@ class BasicChecker extends PKIXCertPathChecker { ...@@ -207,8 +206,8 @@ class BasicChecker extends PKIXCertPathChecker {
debug.println("---checking " + msg + "..."); debug.println("---checking " + msg + "...");
X500Principal currIssuer = cert.getIssuerX500Principal(); X500Principal currIssuer = cert.getIssuerX500Principal();
// reject null or empty issuer DNs
// reject null or empty issuer DNs
if (X500Name.asX500Name(currIssuer).isEmpty()) { if (X500Name.asX500Name(currIssuer).isEmpty()) {
throw new CertPathValidatorException throw new CertPathValidatorException
(msg + " check failed: " + (msg + " check failed: " +
......
/* /*
* Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import sun.security.util.Debug;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
/** /**
...@@ -39,7 +38,6 @@ import java.security.cert.X509Certificate; ...@@ -39,7 +38,6 @@ import java.security.cert.X509Certificate;
*/ */
public class BuildStep { public class BuildStep {
private static final Debug debug = Debug.getInstance("certpath");
private Vertex vertex; private Vertex vertex;
private X509Certificate cert; private X509Certificate cert;
private Throwable throwable; private Throwable throwable;
...@@ -86,7 +84,7 @@ public class BuildStep { ...@@ -86,7 +84,7 @@ public class BuildStep {
public BuildStep(Vertex vtx, int res) { public BuildStep(Vertex vtx, int res) {
vertex = vtx; vertex = vtx;
if (vertex != null) { if (vertex != null) {
cert = (X509Certificate)vertex.getCertificate(); cert = vertex.getCertificate();
throwable = vertex.getThrowable(); throwable = vertex.getThrowable();
} }
result = res; result = res;
...@@ -117,7 +115,7 @@ public class BuildStep { ...@@ -117,7 +115,7 @@ public class BuildStep {
* @returns String form of issuer name or null, if no certificate. * @returns String form of issuer name or null, if no certificate.
*/ */
public String getIssuerName() { public String getIssuerName() {
return (cert == null ? null : cert.getIssuerX500Principal().toString()); return getIssuerName(null);
} }
/** /**
...@@ -142,7 +140,7 @@ public class BuildStep { ...@@ -142,7 +140,7 @@ public class BuildStep {
* @returns String form of subject name or null, if no certificate. * @returns String form of subject name or null, if no certificate.
*/ */
public String getSubjectName() { public String getSubjectName() {
return (cert == null ? null : cert.getSubjectX500Principal().toString()); return getSubjectName(null);
} }
/** /**
...@@ -191,21 +189,21 @@ public class BuildStep { ...@@ -191,21 +189,21 @@ public class BuildStep {
public String resultToString(int res) { public String resultToString(int res) {
String resultString = ""; String resultString = "";
switch (res) { switch (res) {
case BuildStep.POSSIBLE: case POSSIBLE:
resultString = "Certificate to be tried.\n"; resultString = "Certificate to be tried.\n";
break; break;
case BuildStep.BACK: case BACK:
resultString = "Certificate backed out since path does not " resultString = "Certificate backed out since path does not "
+ "satisfy build requirements.\n"; + "satisfy build requirements.\n";
break; break;
case BuildStep.FOLLOW: case FOLLOW:
resultString = "Certificate satisfies conditions.\n"; resultString = "Certificate satisfies conditions.\n";
break; break;
case BuildStep.FAIL: case FAIL:
resultString = "Certificate backed out since path does not " resultString = "Certificate backed out since path does not "
+ "satisfy conditions.\n"; + "satisfy conditions.\n";
break; break;
case BuildStep.SUCCEED: case SUCCEED:
resultString = "Certificate satisfies conditions.\n"; resultString = "Certificate satisfies conditions.\n";
break; break;
default: default:
...@@ -220,6 +218,7 @@ public class BuildStep { ...@@ -220,6 +218,7 @@ public class BuildStep {
* *
* @returns String * @returns String
*/ */
@Override
public String toString() { public String toString() {
String out = "Internal Error\n"; String out = "Internal Error\n";
switch (result) { switch (result) {
...@@ -273,8 +272,6 @@ public class BuildStep { ...@@ -273,8 +272,6 @@ public class BuildStep {
* @returns String * @returns String
*/ */
public String fullToString() { public String fullToString() {
String out = resultToString(getResult()); return resultToString(getResult()) + vertex.toString();
out = out + vertex.toString();
return out;
} }
} }
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,9 +31,8 @@ import java.security.GeneralSecurityException; ...@@ -31,9 +31,8 @@ import java.security.GeneralSecurityException;
import java.security.cert.*; import java.security.cert.*;
import java.util.*; import java.util.*;
import javax.security.auth.x500.X500Principal;
import sun.security.action.GetBooleanAction; import sun.security.action.GetBooleanAction;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.GeneralNames; import sun.security.x509.GeneralNames;
import sun.security.x509.GeneralNameInterface; import sun.security.x509.GeneralNameInterface;
...@@ -56,9 +55,7 @@ public abstract class Builder { ...@@ -56,9 +55,7 @@ public abstract class Builder {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private Set<String> matchingPolicies; private Set<String> matchingPolicies;
final PKIXBuilderParameters buildParams; final BuilderParams buildParams;
final X500Principal targetSubjectDN;
final Date date;
final X509CertSelector targetCertConstraints; final X509CertSelector targetCertConstraints;
/** /**
...@@ -74,14 +71,10 @@ public abstract class Builder { ...@@ -74,14 +71,10 @@ public abstract class Builder {
* *
* @param params the parameter set used to build a certification path * @param params the parameter set used to build a certification path
*/ */
Builder(PKIXBuilderParameters buildParams, X500Principal targetSubjectDN) { Builder(BuilderParams buildParams) {
this.buildParams = buildParams; this.buildParams = buildParams;
this.targetSubjectDN = targetSubjectDN;
// Initialize date if not specified
Date paramsDate = buildParams.getDate();
this.date = paramsDate != null ? paramsDate : new Date();
this.targetCertConstraints = this.targetCertConstraints =
(X509CertSelector) buildParams.getTargetCertConstraints(); (X509CertSelector)buildParams.targetCertConstraints();
} }
/** /**
...@@ -104,7 +97,8 @@ public abstract class Builder { ...@@ -104,7 +97,8 @@ public abstract class Builder {
* @param certPathList the certPathList generated thus far * @param certPathList the certPathList generated thus far
*/ */
abstract void verifyCert(X509Certificate cert, State currentState, abstract void verifyCert(X509Certificate cert, State currentState,
List<X509Certificate> certPathList) throws GeneralSecurityException; List<X509Certificate> certPathList)
throws GeneralSecurityException;
/** /**
* Verifies whether the input certificate completes the path. * Verifies whether the input certificate completes the path.
...@@ -123,7 +117,7 @@ public abstract class Builder { ...@@ -123,7 +117,7 @@ public abstract class Builder {
* @param certPathList the certification path list * @param certPathList the certification path list
*/ */
abstract void addCertToPath(X509Certificate cert, abstract void addCertToPath(X509Certificate cert,
LinkedList<X509Certificate> certPathList); LinkedList<X509Certificate> certPathList);
/** /**
* Removes final certificate from the certPathList * Removes final certificate from the certPathList
...@@ -147,7 +141,8 @@ public abstract class Builder { ...@@ -147,7 +141,8 @@ public abstract class Builder {
* is a grandparent, etc. * is a grandparent, etc.
*/ */
static int distance(GeneralNameInterface base, static int distance(GeneralNameInterface base,
GeneralNameInterface test, int incomparable) { GeneralNameInterface test, int incomparable)
{
switch (base.constrains(test)) { switch (base.constrains(test)) {
case GeneralNameInterface.NAME_DIFF_TYPE: case GeneralNameInterface.NAME_DIFF_TYPE:
if (debug != null) { if (debug != null) {
...@@ -192,7 +187,8 @@ public abstract class Builder { ...@@ -192,7 +187,8 @@ public abstract class Builder {
* some number of down hops. * some number of down hops.
*/ */
static int hops(GeneralNameInterface base, GeneralNameInterface test, static int hops(GeneralNameInterface base, GeneralNameInterface test,
int incomparable) { int incomparable)
{
int baseRtest = base.constrains(test); int baseRtest = base.constrains(test);
switch (baseRtest) { switch (baseRtest) {
case GeneralNameInterface.NAME_DIFF_TYPE: case GeneralNameInterface.NAME_DIFF_TYPE:
...@@ -282,9 +278,9 @@ public abstract class Builder { ...@@ -282,9 +278,9 @@ public abstract class Builder {
* @throws IOException if certificate does not get closer * @throws IOException if certificate does not get closer
*/ */
static int targetDistance(NameConstraintsExtension constraints, static int targetDistance(NameConstraintsExtension constraints,
X509Certificate cert, GeneralNameInterface target) X509Certificate cert, GeneralNameInterface target)
throws IOException { throws IOException
{
/* ensure that certificate satisfies existing name constraints */ /* ensure that certificate satisfies existing name constraints */
if (constraints != null && !constraints.verify(cert)) { if (constraints != null && !constraints.verify(cert)) {
throw new IOException("certificate does not satisfy existing name " throw new IOException("certificate does not satisfy existing name "
...@@ -295,7 +291,7 @@ public abstract class Builder { ...@@ -295,7 +291,7 @@ public abstract class Builder {
try { try {
certImpl = X509CertImpl.toImpl(cert); certImpl = X509CertImpl.toImpl(cert);
} catch (CertificateException e) { } catch (CertificateException e) {
throw (IOException)new IOException("Invalid certificate").initCause(e); throw new IOException("Invalid certificate", e);
} }
/* see if certificate subject matches target */ /* see if certificate subject matches target */
X500Name subject = X500Name.asX500Name(certImpl.getSubjectX500Principal()); X500Name subject = X500Name.asX500Name(certImpl.getSubjectX500Principal());
...@@ -398,13 +394,13 @@ public abstract class Builder { ...@@ -398,13 +394,13 @@ public abstract class Builder {
*/ */
Set<String> getMatchingPolicies() { Set<String> getMatchingPolicies() {
if (matchingPolicies != null) { if (matchingPolicies != null) {
Set<String> initialPolicies = buildParams.getInitialPolicies(); Set<String> initialPolicies = buildParams.initialPolicies();
if ((!initialPolicies.isEmpty()) && if ((!initialPolicies.isEmpty()) &&
(!initialPolicies.contains(PolicyChecker.ANY_POLICY)) && (!initialPolicies.contains(PolicyChecker.ANY_POLICY)) &&
(buildParams.isPolicyMappingInhibited())) (buildParams.policyMappingInhibited()))
{ {
initialPolicies.add(PolicyChecker.ANY_POLICY); matchingPolicies = new HashSet<>(initialPolicies);
matchingPolicies = initialPolicies; matchingPolicies.add(PolicyChecker.ANY_POLICY);
} else { } else {
// we just return an empty set to make sure that there is // we just return an empty set to make sure that there is
// at least a certificate policies extension in the cert // at least a certificate policies extension in the cert
...@@ -429,13 +425,15 @@ public abstract class Builder { ...@@ -429,13 +425,15 @@ public abstract class Builder {
* Returns true iff resultCerts changed (a cert was added to the collection) * Returns true iff resultCerts changed (a cert was added to the collection)
*/ */
boolean addMatchingCerts(X509CertSelector selector, boolean addMatchingCerts(X509CertSelector selector,
Collection<CertStore> certStores, Collection<CertStore> certStores,
Collection<X509Certificate> resultCerts, boolean checkAll) { Collection<X509Certificate> resultCerts,
boolean checkAll)
{
X509Certificate targetCert = selector.getCertificate(); X509Certificate targetCert = selector.getCertificate();
if (targetCert != null) { if (targetCert != null) {
// no need to search CertStores // no need to search CertStores
if (selector.match(targetCert) && !X509CertImpl.isSelfSigned if (selector.match(targetCert) && !X509CertImpl.isSelfSigned
(targetCert, buildParams.getSigProvider())) { (targetCert, buildParams.sigProvider())) {
if (debug != null) { if (debug != null) {
debug.println("Builder.addMatchingCerts: adding target cert"); debug.println("Builder.addMatchingCerts: adding target cert");
} }
...@@ -450,7 +448,7 @@ public abstract class Builder { ...@@ -450,7 +448,7 @@ public abstract class Builder {
store.getCertificates(selector); store.getCertificates(selector);
for (Certificate cert : certs) { for (Certificate cert : certs) {
if (!X509CertImpl.isSelfSigned if (!X509CertImpl.isSelfSigned
((X509Certificate)cert, buildParams.getSigProvider())) { ((X509Certificate)cert, buildParams.sigProvider())) {
if (resultCerts.add((X509Certificate)cert)) { if (resultCerts.add((X509Certificate)cert)) {
add = true; add = true;
} }
...@@ -471,16 +469,4 @@ public abstract class Builder { ...@@ -471,16 +469,4 @@ public abstract class Builder {
} }
return add; return add;
} }
/**
* Returns true if CertStore is local. Currently, returns true if
* type is Collection or if it has been initialized with
* CollectionCertStoreParameters. A new API method should be added
* to CertStore that returns local or remote.
*/
static boolean isLocalCertStore(CertStore certStore) {
return (certStore.getType().equals("Collection") ||
certStore.getCertStoreParameters() instanceof
CollectionCertStoreParameters);
}
} }
/* /*
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -83,9 +83,8 @@ public abstract class CertStoreHelper { ...@@ -83,9 +83,8 @@ public abstract class CertStoreHelper {
= (CertStoreHelper)c.newInstance(); = (CertStoreHelper)c.newInstance();
cache.put(type, csh); cache.put(type, csh);
return csh; return csh;
} catch (InstantiationException e) { } catch (InstantiationException |
throw new AssertionError(e); IllegalAccessException e) {
} catch (IllegalAccessException e) {
throw new AssertionError(e); throw new AssertionError(e);
} }
} }
......
/* /*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -31,7 +31,6 @@ import java.security.cert.CRL; ...@@ -31,7 +31,6 @@ import java.security.cert.CRL;
import java.util.Collection; import java.util.Collection;
import java.util.ConcurrentModificationException; import java.util.ConcurrentModificationException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.security.cert.CertSelector; import java.security.cert.CertSelector;
import java.security.cert.CertStore; import java.security.cert.CertStore;
import java.security.cert.CertStoreException; import java.security.cert.CertStoreException;
...@@ -114,6 +113,7 @@ public class CollectionCertStore extends CertStoreSpi { ...@@ -114,6 +113,7 @@ public class CollectionCertStore extends CertStoreSpi {
* match the specified selector * match the specified selector
* @throws CertStoreException if an exception occurs * @throws CertStoreException if an exception occurs
*/ */
@Override
public Collection<Certificate> engineGetCertificates public Collection<Certificate> engineGetCertificates
(CertSelector selector) throws CertStoreException { (CertSelector selector) throws CertStoreException {
if (coll == null) { if (coll == null) {
...@@ -122,18 +122,15 @@ public class CollectionCertStore extends CertStoreSpi { ...@@ -122,18 +122,15 @@ public class CollectionCertStore extends CertStoreSpi {
// Tolerate a few ConcurrentModificationExceptions // Tolerate a few ConcurrentModificationExceptions
for (int c = 0; c < 10; c++) { for (int c = 0; c < 10; c++) {
try { try {
HashSet<Certificate> result = new HashSet<Certificate>(); HashSet<Certificate> result = new HashSet<>();
Iterator<?> i = coll.iterator();
if (selector != null) { if (selector != null) {
while (i.hasNext()) { for (Object o : coll) {
Object o = i.next();
if ((o instanceof Certificate) && if ((o instanceof Certificate) &&
selector.match((Certificate) o)) selector.match((Certificate) o))
result.add((Certificate)o); result.add((Certificate)o);
} }
} else { } else {
while (i.hasNext()) { for (Object o : coll) {
Object o = i.next();
if (o instanceof Certificate) if (o instanceof Certificate)
result.add((Certificate)o); result.add((Certificate)o);
} }
...@@ -157,6 +154,7 @@ public class CollectionCertStore extends CertStoreSpi { ...@@ -157,6 +154,7 @@ public class CollectionCertStore extends CertStoreSpi {
* match the specified selector * match the specified selector
* @throws CertStoreException if an exception occurs * @throws CertStoreException if an exception occurs
*/ */
@Override
public Collection<CRL> engineGetCRLs(CRLSelector selector) public Collection<CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException throws CertStoreException
{ {
...@@ -166,22 +164,19 @@ public class CollectionCertStore extends CertStoreSpi { ...@@ -166,22 +164,19 @@ public class CollectionCertStore extends CertStoreSpi {
// Tolerate a few ConcurrentModificationExceptions // Tolerate a few ConcurrentModificationExceptions
for (int c = 0; c < 10; c++) { for (int c = 0; c < 10; c++) {
try { try {
HashSet<CRL> result = new HashSet<CRL>(); HashSet<CRL> result = new HashSet<>();
Iterator<?> i = coll.iterator();
if (selector != null) { if (selector != null) {
while (i.hasNext()) { for (Object o : coll) {
Object o = i.next();
if ((o instanceof CRL) && selector.match((CRL) o)) if ((o instanceof CRL) && selector.match((CRL) o))
result.add((CRL)o); result.add((CRL)o);
} }
} else { } else {
while (i.hasNext()) { for (Object o : coll) {
Object o = i.next();
if (o instanceof CRL) if (o instanceof CRL)
result.add((CRL)o); result.add((CRL)o);
} }
} }
return(result); return result;
} catch (ConcurrentModificationException e) { } } catch (ConcurrentModificationException e) { }
} }
throw new ConcurrentModificationException("Too many " throw new ConcurrentModificationException("Too many "
......
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,19 +25,20 @@ ...@@ -25,19 +25,20 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import java.util.HashSet;
import java.io.IOException; import java.io.IOException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
import java.security.cert.X509Certificate;
import java.security.cert.PKIXCertPathChecker; import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXReason; import java.security.cert.PKIXReason;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.PKIXExtensions; import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.NameConstraintsExtension; import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
...@@ -66,13 +67,12 @@ class ConstraintsChecker extends PKIXCertPathChecker { ...@@ -66,13 +67,12 @@ class ConstraintsChecker extends PKIXCertPathChecker {
* Creates a ConstraintsChecker. * Creates a ConstraintsChecker.
* *
* @param certPathLength the length of the certification path * @param certPathLength the length of the certification path
* @throws CertPathValidatorException if the checker cannot be initialized
*/ */
ConstraintsChecker(int certPathLength) throws CertPathValidatorException { ConstraintsChecker(int certPathLength) {
this.certPathLength = certPathLength; this.certPathLength = certPathLength;
init(false);
} }
@Override
public void init(boolean forward) throws CertPathValidatorException { public void init(boolean forward) throws CertPathValidatorException {
if (!forward) { if (!forward) {
i = 0; i = 0;
...@@ -84,15 +84,17 @@ class ConstraintsChecker extends PKIXCertPathChecker { ...@@ -84,15 +84,17 @@ class ConstraintsChecker extends PKIXCertPathChecker {
} }
} }
@Override
public boolean isForwardCheckingSupported() { public boolean isForwardCheckingSupported() {
return false; return false;
} }
@Override
public Set<String> getSupportedExtensions() { public Set<String> getSupportedExtensions() {
if (supportedExts == null) { if (supportedExts == null) {
supportedExts = new HashSet<String>(); supportedExts = new HashSet<String>(2);
supportedExts.add(PKIXExtensions.BasicConstraints_Id.toString()); supportedExts.add(BasicConstraints_Id.toString());
supportedExts.add(PKIXExtensions.NameConstraints_Id.toString()); supportedExts.add(NameConstraints_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts); supportedExts = Collections.unmodifiableSet(supportedExts);
} }
return supportedExts; return supportedExts;
...@@ -104,14 +106,15 @@ class ConstraintsChecker extends PKIXCertPathChecker { ...@@ -104,14 +106,15 @@ class ConstraintsChecker extends PKIXCertPathChecker {
* *
* @param cert the <code>Certificate</code> to be checked * @param cert the <code>Certificate</code> to be checked
* @param unresCritExts a <code>Collection</code> of OID strings * @param unresCritExts a <code>Collection</code> of OID strings
* representing the current set of unresolved critical extensions * representing the current set of unresolved critical extensions
* @throws CertPathValidatorException if the specified certificate * @throws CertPathValidatorException if the specified certificate
* does not pass the check * does not pass the check
*/ */
@Override
public void check(Certificate cert, Collection<String> unresCritExts) public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException throws CertPathValidatorException
{ {
X509Certificate currCert = (X509Certificate) cert; X509Certificate currCert = (X509Certificate)cert;
i++; i++;
// MUST run NC check second, since it depends on BC check to // MUST run NC check second, since it depends on BC check to
...@@ -120,8 +123,8 @@ class ConstraintsChecker extends PKIXCertPathChecker { ...@@ -120,8 +123,8 @@ class ConstraintsChecker extends PKIXCertPathChecker {
verifyNameConstraints(currCert); verifyNameConstraints(currCert);
if (unresCritExts != null && !unresCritExts.isEmpty()) { if (unresCritExts != null && !unresCritExts.isEmpty()) {
unresCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString()); unresCritExts.remove(BasicConstraints_Id.toString());
unresCritExts.remove(PKIXExtensions.NameConstraints_Id.toString()); unresCritExts.remove(NameConstraints_Id.toString());
} }
} }
...@@ -166,9 +169,9 @@ class ConstraintsChecker extends PKIXCertPathChecker { ...@@ -166,9 +169,9 @@ class ConstraintsChecker extends PKIXCertPathChecker {
/** /**
* Helper to fold sets of name constraints together * Helper to fold sets of name constraints together
*/ */
static NameConstraintsExtension static NameConstraintsExtension mergeNameConstraints(
mergeNameConstraints(X509Certificate currCert, X509Certificate currCert, NameConstraintsExtension prevNC)
NameConstraintsExtension prevNC) throws CertPathValidatorException throws CertPathValidatorException
{ {
X509CertImpl currCertImpl; X509CertImpl currCertImpl;
try { try {
...@@ -197,7 +200,7 @@ class ConstraintsChecker extends PKIXCertPathChecker { ...@@ -197,7 +200,7 @@ class ConstraintsChecker extends PKIXCertPathChecker {
// Make sure we do a clone here, because we're probably // Make sure we do a clone here, because we're probably
// going to modify this object later and we don't want to // going to modify this object later and we don't want to
// be sharing it with a Certificate object! // be sharing it with a Certificate object!
return (NameConstraintsExtension) newConstraints.clone(); return (NameConstraintsExtension)newConstraints.clone();
} }
} else { } else {
try { try {
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -27,14 +27,14 @@ package sun.security.provider.certpath; ...@@ -27,14 +27,14 @@ package sun.security.provider.certpath;
import java.io.*; import java.io.*;
import java.net.URI; import java.net.URI;
import java.util.*;
import java.security.*; import java.security.*;
import java.security.cert.*; import java.security.cert.*;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import java.util.*;
import sun.security.action.GetBooleanAction;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.util.DerOutputStream; import sun.security.util.DerOutputStream;
import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.*; import sun.security.x509.*;
/** /**
...@@ -57,45 +57,24 @@ class DistributionPointFetcher { ...@@ -57,45 +57,24 @@ class DistributionPointFetcher {
private static final boolean[] ALL_REASONS = private static final boolean[] ALL_REASONS =
{true, true, true, true, true, true, true, true, true}; {true, true, true, true, true, true, true, true, true};
/**
* Flag indicating whether support for the CRL distribution point
* extension shall be enabled. Currently disabled by default for
* compatibility and legal reasons.
*/
private final static boolean USE_CRLDP = AccessController.doPrivileged
(new GetBooleanAction("com.sun.security.enableCRLDP"));
// singleton instance
private static final DistributionPointFetcher INSTANCE =
new DistributionPointFetcher();
/** /**
* Private instantiation only. * Private instantiation only.
*/ */
private DistributionPointFetcher() {} private DistributionPointFetcher() {}
/**
* Return a DistributionPointFetcher instance.
*/
static DistributionPointFetcher getInstance() {
return INSTANCE;
}
/** /**
* Return the X509CRLs matching this selector. The selector must be * Return the X509CRLs matching this selector. The selector must be
* an X509CRLSelector with certificateChecking set. * an X509CRLSelector with certificateChecking set.
*
* If CRLDP support is disabled, this method always returns an
* empty set.
*/ */
Collection<X509CRL> getCRLs(X509CRLSelector selector, boolean signFlag, static Collection<X509CRL> getCRLs(X509CRLSelector selector,
PublicKey prevKey, String provider, List<CertStore> certStores, boolean signFlag, PublicKey prevKey,
boolean[] reasonsMask, Set<TrustAnchor> trustAnchors, String provider,
Date validity) throws CertStoreException { List<CertStore> certStores,
boolean[] reasonsMask,
if (USE_CRLDP == false) { Set<TrustAnchor> trustAnchors,
return Collections.emptySet(); Date validity)
} throws CertStoreException
{
X509Certificate cert = selector.getCertificateChecking(); X509Certificate cert = selector.getCertificateChecking();
if (cert == null) { if (cert == null) {
return Collections.emptySet(); return Collections.emptySet();
...@@ -116,7 +95,7 @@ class DistributionPointFetcher { ...@@ -116,7 +95,7 @@ class DistributionPointFetcher {
} }
List<DistributionPoint> points = List<DistributionPoint> points =
ext.get(CRLDistributionPointsExtension.POINTS); ext.get(CRLDistributionPointsExtension.POINTS);
Set<X509CRL> results = new HashSet<X509CRL>(); Set<X509CRL> results = new HashSet<>();
for (Iterator<DistributionPoint> t = points.iterator(); for (Iterator<DistributionPoint> t = points.iterator();
t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) { t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
DistributionPoint point = t.next(); DistributionPoint point = t.next();
...@@ -129,9 +108,7 @@ class DistributionPointFetcher { ...@@ -129,9 +108,7 @@ class DistributionPointFetcher {
debug.println("Returning " + results.size() + " CRLs"); debug.println("Returning " + results.size() + " CRLs");
} }
return results; return results;
} catch (CertificateException e) { } catch (CertificateException | IOException e) {
return Collections.emptySet();
} catch (IOException e) {
return Collections.emptySet(); return Collections.emptySet();
} }
} }
...@@ -140,7 +117,7 @@ class DistributionPointFetcher { ...@@ -140,7 +117,7 @@ class DistributionPointFetcher {
* Download CRLs from the given distribution point, verify and return them. * Download CRLs from the given distribution point, verify and return them.
* See the top of the class for current limitations. * See the top of the class for current limitations.
*/ */
private Collection<X509CRL> getCRLs(X509CRLSelector selector, private static Collection<X509CRL> getCRLs(X509CRLSelector selector,
X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask, X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
boolean signFlag, PublicKey prevKey, String provider, boolean signFlag, PublicKey prevKey, String provider,
List<CertStore> certStores, Set<TrustAnchor> trustAnchors, List<CertStore> certStores, Set<TrustAnchor> trustAnchors,
...@@ -200,7 +177,7 @@ class DistributionPointFetcher { ...@@ -200,7 +177,7 @@ class DistributionPointFetcher {
certStores, validity)) { certStores, validity)) {
crls.add(crl); crls.add(crl);
} }
} catch (Exception e) { } catch (IOException | CRLException e) {
// don't add the CRL // don't add the CRL
if (debug != null) { if (debug != null) {
debug.println("Exception verifying CRL: " + e.getMessage()); debug.println("Exception verifying CRL: " + e.getMessage());
...@@ -214,7 +191,7 @@ class DistributionPointFetcher { ...@@ -214,7 +191,7 @@ class DistributionPointFetcher {
/** /**
* Download CRL from given URI. * Download CRL from given URI.
*/ */
private X509CRL getCRL(URIName name) { private static X509CRL getCRL(URIName name) {
URI uri = name.getURI(); URI uri = name.getURI();
if (debug != null) { if (debug != null) {
debug.println("Trying to fetch CRL from DP " + uri); debug.println("Trying to fetch CRL from DP " + uri);
...@@ -240,7 +217,7 @@ class DistributionPointFetcher { ...@@ -240,7 +217,7 @@ class DistributionPointFetcher {
/** /**
* Fetch CRLs from certStores. * Fetch CRLs from certStores.
*/ */
private Collection<X509CRL> getCRLs(X500Name name, private static Collection<X509CRL> getCRLs(X500Name name,
X500Principal certIssuer, List<CertStore> certStores) X500Principal certIssuer, List<CertStore> certStores)
{ {
if (debug != null) { if (debug != null) {
...@@ -249,7 +226,7 @@ class DistributionPointFetcher { ...@@ -249,7 +226,7 @@ class DistributionPointFetcher {
X509CRLSelector xcs = new X509CRLSelector(); X509CRLSelector xcs = new X509CRLSelector();
xcs.addIssuer(name.asX500Principal()); xcs.addIssuer(name.asX500Principal());
xcs.addIssuer(certIssuer); xcs.addIssuer(certIssuer);
Collection<X509CRL> crls = new ArrayList<X509CRL>(); Collection<X509CRL> crls = new ArrayList<>();
for (CertStore store : certStores) { for (CertStore store : certStores) {
try { try {
for (CRL crl : store.getCRLs(xcs)) { for (CRL crl : store.getCRLs(xcs)) {
...@@ -285,7 +262,7 @@ class DistributionPointFetcher { ...@@ -285,7 +262,7 @@ class DistributionPointFetcher {
* certification path should be determined * certification path should be determined
* @return true if ok, false if not * @return true if ok, false if not
*/ */
boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point, static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
X509CRL crl, boolean[] reasonsMask, boolean signFlag, X509CRL crl, boolean[] reasonsMask, boolean signFlag,
PublicKey prevKey, String provider, PublicKey prevKey, String provider,
Set<TrustAnchor> trustAnchors, List<CertStore> certStores, Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
...@@ -340,9 +317,9 @@ class DistributionPointFetcher { ...@@ -340,9 +317,9 @@ class DistributionPointFetcher {
} else { } else {
// in case of self-issued indirect CRL issuer. // in case of self-issued indirect CRL issuer.
byte[] certAKID = certImpl.getExtensionValue( byte[] certAKID = certImpl.getExtensionValue(
PKIXExtensions.AuthorityKey_Id.toString()); AuthorityKey_Id.toString());
byte[] crlAKID = crlImpl.getExtensionValue( byte[] crlAKID = crlImpl.getExtensionValue(
PKIXExtensions.AuthorityKey_Id.toString()); AuthorityKey_Id.toString());
if (certAKID == null || crlAKID == null) { if (certAKID == null || crlAKID == null) {
// cannot recognize indirect CRL without AKID // cannot recognize indirect CRL without AKID
...@@ -539,7 +516,7 @@ class DistributionPointFetcher { ...@@ -539,7 +516,7 @@ class DistributionPointFetcher {
// verify that interim reasons mask includes one or more reasons // verify that interim reasons mask includes one or more reasons
// not included in the reasons mask // not included in the reasons mask
boolean oneOrMore = false; boolean oneOrMore = false;
for (int i=0; i < interimReasonsMask.length && !oneOrMore; i++) { for (int i = 0; i < interimReasonsMask.length && !oneOrMore; i++) {
if (!reasonsMask[i] && interimReasonsMask[i]) { if (!reasonsMask[i] && interimReasonsMask[i]) {
oneOrMore = true; oneOrMore = true;
} }
...@@ -615,7 +592,7 @@ class DistributionPointFetcher { ...@@ -615,7 +592,7 @@ class DistributionPointFetcher {
PKIXCertPathBuilderResult result = PKIXCertPathBuilderResult result =
(PKIXCertPathBuilderResult) builder.build(params); (PKIXCertPathBuilderResult) builder.build(params);
prevKey = result.getPublicKey(); prevKey = result.getPublicKey();
} catch (Exception e) { } catch (GeneralSecurityException e) {
throw new CRLException(e); throw new CRLException(e);
} }
} }
...@@ -633,7 +610,7 @@ class DistributionPointFetcher { ...@@ -633,7 +610,7 @@ class DistributionPointFetcher {
// validate the signature on the CRL // validate the signature on the CRL
try { try {
crl.verify(prevKey, provider); crl.verify(prevKey, provider);
} catch (Exception e) { } catch (GeneralSecurityException e) {
if (debug != null) { if (debug != null) {
debug.println("CRL signature failed to verify"); debug.println("CRL signature failed to verify");
} }
...@@ -644,22 +621,21 @@ class DistributionPointFetcher { ...@@ -644,22 +621,21 @@ class DistributionPointFetcher {
Set<String> unresCritExts = crl.getCriticalExtensionOIDs(); Set<String> unresCritExts = crl.getCriticalExtensionOIDs();
// remove any that we have processed // remove any that we have processed
if (unresCritExts != null) { if (unresCritExts != null) {
unresCritExts.remove unresCritExts.remove(IssuingDistributionPoint_Id.toString());
(PKIXExtensions.IssuingDistributionPoint_Id.toString());
if (!unresCritExts.isEmpty()) { if (!unresCritExts.isEmpty()) {
if (debug != null) { if (debug != null) {
debug.println("Unrecognized critical extension(s) in CRL: " debug.println("Unrecognized critical extension(s) in CRL: "
+ unresCritExts); + unresCritExts);
Iterator<String> i = unresCritExts.iterator(); for (String ext : unresCritExts) {
while (i.hasNext()) debug.println(ext);
debug.println(i.next()); }
} }
return false; return false;
} }
} }
// update reasonsMask // update reasonsMask
for (int i=0; i < interimReasonsMask.length; i++) { for (int i = 0; i < interimReasonsMask.length; i++) {
if (!reasonsMask[i] && interimReasonsMask[i]) { if (!reasonsMask[i] && interimReasonsMask[i]) {
reasonsMask[i] = true; reasonsMask[i] = true;
} }
...@@ -671,9 +647,10 @@ class DistributionPointFetcher { ...@@ -671,9 +647,10 @@ class DistributionPointFetcher {
* Append relative name to the issuer name and return a new * Append relative name to the issuer name and return a new
* GeneralNames object. * GeneralNames object.
*/ */
private GeneralNames getFullNames(X500Name issuer, RDN rdn) private static GeneralNames getFullNames(X500Name issuer, RDN rdn)
throws IOException { throws IOException
List<RDN> rdns = new ArrayList<RDN>(issuer.rdns()); {
List<RDN> rdns = new ArrayList<>(issuer.rdns());
rdns.add(rdn); rdns.add(rdn);
X500Name fullName = new X500Name(rdns.toArray(new RDN[0])); X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));
GeneralNames fullNames = new GeneralNames(); GeneralNames fullNames = new GeneralNames();
...@@ -681,15 +658,16 @@ class DistributionPointFetcher { ...@@ -681,15 +658,16 @@ class DistributionPointFetcher {
return fullNames; return fullNames;
} }
/** Verifies whether a CRL is issued by a certain certificate /**
* Verifies whether a CRL is issued by a certain certificate
* *
* @param cert the certificate * @param cert the certificate
* @param crl the CRL to be verified * @param crl the CRL to be verified
* @param provider the name of the signature provider * @param provider the name of the signature provider
*/ */
private static boolean issues(X509CertImpl cert, X509CRLImpl crl, private static boolean issues(X509CertImpl cert, X509CRLImpl crl,
String provider) throws IOException { String provider) throws IOException
{
boolean matched = false; boolean matched = false;
AdaptableX509CertSelector issuerSelector = AdaptableX509CertSelector issuerSelector =
...@@ -727,7 +705,7 @@ class DistributionPointFetcher { ...@@ -727,7 +705,7 @@ class DistributionPointFetcher {
try { try {
crl.verify(cert.getPublicKey(), provider); crl.verify(cert.getPublicKey(), provider);
matched = true; matched = true;
} catch (Exception e) { } catch (GeneralSecurityException e) {
matched = false; matched = false;
} }
} }
......
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,10 +26,9 @@ ...@@ -26,10 +26,9 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.io.IOException; import java.io.IOException;
import java.util.*;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.PublicKey;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
import java.security.cert.PKIXReason; import java.security.cert.PKIXReason;
...@@ -40,12 +39,14 @@ import java.security.cert.PKIXCertPathChecker; ...@@ -40,12 +39,14 @@ import java.security.cert.PKIXCertPathChecker;
import java.security.cert.TrustAnchor; import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.security.cert.X509CertSelector; import java.security.cert.X509CertSelector;
import java.util.*;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.AccessDescription; import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.PKIXExtensions; import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.PolicyMappingsExtension; import sun.security.x509.PolicyMappingsExtension;
import sun.security.x509.X500Name; import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
...@@ -72,21 +73,17 @@ class ForwardBuilder extends Builder { ...@@ -72,21 +73,17 @@ class ForwardBuilder extends Builder {
TrustAnchor trustAnchor; TrustAnchor trustAnchor;
private Comparator<X509Certificate> comparator; private Comparator<X509Certificate> comparator;
private boolean searchAllCertStores = true; private boolean searchAllCertStores = true;
private boolean onlyEECert = false;
/** /**
* Initialize the builder with the input parameters. * Initialize the builder with the input parameters.
* *
* @param params the parameter set used to build a certification path * @param params the parameter set used to build a certification path
*/ */
ForwardBuilder(PKIXBuilderParameters buildParams, ForwardBuilder(BuilderParams buildParams, boolean searchAllCertStores) {
X500Principal targetSubjectDN, boolean searchAllCertStores, super(buildParams);
boolean onlyEECert)
{
super(buildParams, targetSubjectDN);
// populate sets of trusted certificates and subject DNs // populate sets of trusted certificates and subject DNs
trustAnchors = buildParams.getTrustAnchors(); trustAnchors = buildParams.trustAnchors();
trustedCerts = new HashSet<X509Certificate>(trustAnchors.size()); trustedCerts = new HashSet<X509Certificate>(trustAnchors.size());
trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size()); trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size());
for (TrustAnchor anchor : trustAnchors) { for (TrustAnchor anchor : trustAnchors) {
...@@ -100,7 +97,6 @@ class ForwardBuilder extends Builder { ...@@ -100,7 +97,6 @@ class ForwardBuilder extends Builder {
} }
comparator = new PKIXCertComparator(trustedSubjectDNs); comparator = new PKIXCertComparator(trustedSubjectDNs);
this.searchAllCertStores = searchAllCertStores; this.searchAllCertStores = searchAllCertStores;
this.onlyEECert = onlyEECert;
} }
/** /**
...@@ -112,8 +108,9 @@ class ForwardBuilder extends Builder { ...@@ -112,8 +108,9 @@ class ForwardBuilder extends Builder {
* Must be an instance of <code>ForwardState</code> * Must be an instance of <code>ForwardState</code>
* @param certStores list of CertStores * @param certStores list of CertStores
*/ */
Collection<X509Certificate> getMatchingCerts @Override
(State currentState, List<CertStore> certStores) Collection<X509Certificate> getMatchingCerts(State currentState,
List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException throws CertStoreException, CertificateException, IOException
{ {
if (debug != null) { if (debug != null) {
...@@ -127,7 +124,7 @@ class ForwardBuilder extends Builder { ...@@ -127,7 +124,7 @@ class ForwardBuilder extends Builder {
* As each cert is added, it is sorted based on the PKIXCertComparator * As each cert is added, it is sorted based on the PKIXCertComparator
* algorithm. * algorithm.
*/ */
Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator); Set<X509Certificate> certs = new TreeSet<>(comparator);
/* /*
* Only look for EE certs if search has just started. * Only look for EE certs if search has just started.
...@@ -145,9 +142,10 @@ class ForwardBuilder extends Builder { ...@@ -145,9 +142,10 @@ class ForwardBuilder extends Builder {
* and requirements specified in the parameters and PKIX state. * and requirements specified in the parameters and PKIX state.
*/ */
private void getMatchingEECerts(ForwardState currentState, private void getMatchingEECerts(ForwardState currentState,
List<CertStore> certStores, Collection<X509Certificate> eeCerts) List<CertStore> certStores,
throws IOException { Collection<X509Certificate> eeCerts)
throws IOException
{
if (debug != null) { if (debug != null) {
debug.println("ForwardBuilder.getMatchingEECerts()..."); debug.println("ForwardBuilder.getMatchingEECerts()...");
} }
...@@ -165,12 +163,12 @@ class ForwardBuilder extends Builder { ...@@ -165,12 +163,12 @@ class ForwardBuilder extends Builder {
/* /*
* Match on certificate validity date * Match on certificate validity date
*/ */
eeSelector.setCertificateValid(date); eeSelector.setCertificateValid(buildParams.date());
/* /*
* Policy processing optimizations * Policy processing optimizations
*/ */
if (buildParams.isExplicitPolicyRequired()) { if (buildParams.explicitPolicyRequired()) {
eeSelector.setPolicy(getMatchingPolicies()); eeSelector.setPolicy(getMatchingPolicies());
} }
/* /*
...@@ -188,9 +186,10 @@ class ForwardBuilder extends Builder { ...@@ -188,9 +186,10 @@ class ForwardBuilder extends Builder {
* and requirements specified in the parameters and PKIX state. * and requirements specified in the parameters and PKIX state.
*/ */
private void getMatchingCACerts(ForwardState currentState, private void getMatchingCACerts(ForwardState currentState,
List<CertStore> certStores, Collection<X509Certificate> caCerts) List<CertStore> certStores,
throws IOException { Collection<X509Certificate> caCerts)
throws IOException
{
if (debug != null) { if (debug != null) {
debug.println("ForwardBuilder.getMatchingCACerts()..."); debug.println("ForwardBuilder.getMatchingCACerts()...");
} }
...@@ -216,8 +215,8 @@ class ForwardBuilder extends Builder { ...@@ -216,8 +215,8 @@ class ForwardBuilder extends Builder {
} }
if (caTargetSelector == null) { if (caTargetSelector == null) {
caTargetSelector = (X509CertSelector) caTargetSelector =
targetCertConstraints.clone(); (X509CertSelector) targetCertConstraints.clone();
/* /*
* Since we don't check the validity period of trusted * Since we don't check the validity period of trusted
...@@ -229,7 +228,7 @@ class ForwardBuilder extends Builder { ...@@ -229,7 +228,7 @@ class ForwardBuilder extends Builder {
/* /*
* Policy processing optimizations * Policy processing optimizations
*/ */
if (buildParams.isExplicitPolicyRequired()) if (buildParams.explicitPolicyRequired())
caTargetSelector.setPolicy(getMatchingPolicies()); caTargetSelector.setPolicy(getMatchingPolicies());
} }
...@@ -249,7 +248,7 @@ class ForwardBuilder extends Builder { ...@@ -249,7 +248,7 @@ class ForwardBuilder extends Builder {
/* /*
* Policy processing optimizations * Policy processing optimizations
*/ */
if (buildParams.isExplicitPolicyRequired()) if (buildParams.explicitPolicyRequired())
caSelector.setPolicy(getMatchingPolicies()); caSelector.setPolicy(getMatchingPolicies());
} }
...@@ -278,7 +277,7 @@ class ForwardBuilder extends Builder { ...@@ -278,7 +277,7 @@ class ForwardBuilder extends Builder {
* check the validity period * check the validity period
*/ */
caSelector.setValidityPeriod(currentState.cert.getNotBefore(), caSelector.setValidityPeriod(currentState.cert.getNotBefore(),
currentState.cert.getNotAfter()); currentState.cert.getNotAfter());
sel = caSelector; sel = caSelector;
} }
...@@ -307,7 +306,7 @@ class ForwardBuilder extends Builder { ...@@ -307,7 +306,7 @@ class ForwardBuilder extends Builder {
* The trusted certificate matching is completed. We need to match * The trusted certificate matching is completed. We need to match
* on certificate validity date. * on certificate validity date.
*/ */
sel.setCertificateValid(date); sel.setCertificateValid(buildParams.date());
/* /*
* Require CA certs with a pathLenConstraint that allows * Require CA certs with a pathLenConstraint that allows
...@@ -323,11 +322,12 @@ class ForwardBuilder extends Builder { ...@@ -323,11 +322,12 @@ class ForwardBuilder extends Builder {
* certificate pairs. * certificate pairs.
*/ */
if (currentState.isInitial() || if (currentState.isInitial() ||
(buildParams.getMaxPathLength() == -1) || (buildParams.maxPathLength() == -1) ||
(buildParams.getMaxPathLength() > currentState.traversedCACerts)) (buildParams.maxPathLength() > currentState.traversedCACerts))
{ {
if (addMatchingCerts(sel, certStores, if (addMatchingCerts(sel, certStores,
caCerts, searchAllCertStores) && !searchAllCertStores) { caCerts, searchAllCertStores)
&& !searchAllCertStores) {
return; return;
} }
} }
...@@ -356,7 +356,8 @@ class ForwardBuilder extends Builder { ...@@ -356,7 +356,8 @@ class ForwardBuilder extends Builder {
// because of the selector, so the cast is safe // because of the selector, so the cast is safe
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private boolean getCerts(AuthorityInfoAccessExtension aiaExt, private boolean getCerts(AuthorityInfoAccessExtension aiaExt,
Collection<X509Certificate> certs) { Collection<X509Certificate> certs)
{
if (Builder.USE_AIA == false) { if (Builder.USE_AIA == false) {
return false; return false;
} }
...@@ -449,6 +450,7 @@ class ForwardBuilder extends Builder { ...@@ -449,6 +450,7 @@ class ForwardBuilder extends Builder {
* @throws ClassCastException if either argument is not of type * @throws ClassCastException if either argument is not of type
* X509Certificate * X509Certificate
*/ */
@Override
public int compare(X509Certificate oCert1, X509Certificate oCert2) { public int compare(X509Certificate oCert1, X509Certificate oCert2) {
// if certs are the same, return 0 // if certs are the same, return 0
...@@ -651,8 +653,10 @@ class ForwardBuilder extends Builder { ...@@ -651,8 +653,10 @@ class ForwardBuilder extends Builder {
* @param currentState the current state against which the cert is verified * @param currentState the current state against which the cert is verified
* @param certPathList the certPathList generated thus far * @param certPathList the certPathList generated thus far
*/ */
@Override
void verifyCert(X509Certificate cert, State currentState, void verifyCert(X509Certificate cert, State currentState,
List<X509Certificate> certPathList) throws GeneralSecurityException List<X509Certificate> certPathList)
throws GeneralSecurityException
{ {
if (debug != null) { if (debug != null) {
debug.println("ForwardBuilder.verifyCert(SN: " debug.println("ForwardBuilder.verifyCert(SN: "
...@@ -683,7 +687,7 @@ class ForwardBuilder extends Builder { ...@@ -683,7 +687,7 @@ class ForwardBuilder extends Builder {
debug.println("policyMappingFound = " + policyMappingFound); debug.println("policyMappingFound = " + policyMappingFound);
} }
if (cert.equals(cpListCert)) { if (cert.equals(cpListCert)) {
if ((buildParams.isPolicyMappingInhibited()) || if ((buildParams.policyMappingInhibited()) ||
(!policyMappingFound)) { (!policyMappingFound)) {
if (debug != null) { if (debug != null) {
debug.println("loop detected!!"); debug.println("loop detected!!");
...@@ -718,7 +722,7 @@ class ForwardBuilder extends Builder { ...@@ -718,7 +722,7 @@ class ForwardBuilder extends Builder {
* all extensions that all user checkers are capable of * all extensions that all user checkers are capable of
* processing. * processing.
*/ */
for (PKIXCertPathChecker checker : buildParams.getCertPathCheckers()) { for (PKIXCertPathChecker checker : buildParams.certPathCheckers()) {
if (!checker.isForwardCheckingSupported()) { if (!checker.isForwardCheckingSupported()) {
Set<String> supportedExts = checker.getSupportedExtensions(); Set<String> supportedExts = checker.getSupportedExtensions();
if (supportedExts != null) { if (supportedExts != null) {
...@@ -732,23 +736,15 @@ class ForwardBuilder extends Builder { ...@@ -732,23 +736,15 @@ class ForwardBuilder extends Builder {
* to check. If there are any left, throw an exception! * to check. If there are any left, throw an exception!
*/ */
if (!unresCritExts.isEmpty()) { if (!unresCritExts.isEmpty()) {
unresCritExts.remove( unresCritExts.remove(BasicConstraints_Id.toString());
PKIXExtensions.BasicConstraints_Id.toString()); unresCritExts.remove(NameConstraints_Id.toString());
unresCritExts.remove( unresCritExts.remove(CertificatePolicies_Id.toString());
PKIXExtensions.NameConstraints_Id.toString()); unresCritExts.remove(PolicyMappings_Id.toString());
unresCritExts.remove( unresCritExts.remove(PolicyConstraints_Id.toString());
PKIXExtensions.CertificatePolicies_Id.toString()); unresCritExts.remove(InhibitAnyPolicy_Id.toString());
unresCritExts.remove( unresCritExts.remove(SubjectAlternativeName_Id.toString());
PKIXExtensions.PolicyMappings_Id.toString()); unresCritExts.remove(KeyUsage_Id.toString());
unresCritExts.remove( unresCritExts.remove(ExtendedKeyUsage_Id.toString());
PKIXExtensions.PolicyConstraints_Id.toString());
unresCritExts.remove(
PKIXExtensions.InhibitAnyPolicy_Id.toString());
unresCritExts.remove(
PKIXExtensions.SubjectAlternativeName_Id.toString());
unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
unresCritExts.remove(
PKIXExtensions.ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty()) if (!unresCritExts.isEmpty())
throw new CertPathValidatorException throw new CertPathValidatorException
...@@ -785,32 +781,13 @@ class ForwardBuilder extends Builder { ...@@ -785,32 +781,13 @@ class ForwardBuilder extends Builder {
* in order to verify a previous cert * in order to verify a previous cert
*/ */
/*
* Check revocation for the previous cert
*/
if (buildParams.isRevocationEnabled()) {
// first off, see if this cert can authorize revocation...
if (CrlRevocationChecker.certCanSignCrl(cert)) {
// And then check to be sure no key requiring key parameters
// has been encountered
if (!currState.keyParamsNeeded())
// If all that checks out, we can check the
// revocation status of the cert. Otherwise,
// we'll just wait until the end.
currState.crlChecker.check(currState.cert,
cert.getPublicKey(),
true);
}
}
/* /*
* Check signature only if no key requiring key parameters has been * Check signature only if no key requiring key parameters has been
* encountered. * encountered.
*/ */
if (!currState.keyParamsNeeded()) { if (!currState.keyParamsNeeded()) {
(currState.cert).verify(cert.getPublicKey(), (currState.cert).verify(cert.getPublicKey(),
buildParams.getSigProvider()); buildParams.sigProvider());
} }
} }
...@@ -826,6 +803,7 @@ class ForwardBuilder extends Builder { ...@@ -826,6 +803,7 @@ class ForwardBuilder extends Builder {
* @param cert the certificate to test * @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path. * @return a boolean value indicating whether the cert completes the path.
*/ */
@Override
boolean isPathCompleted(X509Certificate cert) { boolean isPathCompleted(X509Certificate cert) {
for (TrustAnchor anchor : trustAnchors) { for (TrustAnchor anchor : trustAnchors) {
if (anchor.getTrustedCert() != null) { if (anchor.getTrustedCert() != null) {
...@@ -837,7 +815,7 @@ class ForwardBuilder extends Builder { ...@@ -837,7 +815,7 @@ class ForwardBuilder extends Builder {
} }
} else { } else {
X500Principal principal = anchor.getCA(); X500Principal principal = anchor.getCA();
java.security.PublicKey publicKey = anchor.getCAPublicKey(); PublicKey publicKey = anchor.getCAPublicKey();
if (principal != null && publicKey != null && if (principal != null && publicKey != null &&
principal.equals(cert.getSubjectX500Principal())) { principal.equals(cert.getSubjectX500Principal())) {
...@@ -856,21 +834,6 @@ class ForwardBuilder extends Builder { ...@@ -856,21 +834,6 @@ class ForwardBuilder extends Builder {
} }
} }
/* Check revocation if it is enabled */
if (buildParams.isRevocationEnabled()) {
try {
CrlRevocationChecker crlChecker = new CrlRevocationChecker
(anchor, buildParams, null, onlyEECert);
crlChecker.check(cert, anchor.getCAPublicKey(), true);
} catch (CertPathValidatorException cpve) {
if (debug != null) {
debug.println("ForwardBuilder.isPathCompleted() cpve");
cpve.printStackTrace();
}
continue;
}
}
/* /*
* Check signature * Check signature
*/ */
...@@ -879,18 +842,17 @@ class ForwardBuilder extends Builder { ...@@ -879,18 +842,17 @@ class ForwardBuilder extends Builder {
// parameters, yet there is no key to inherit the parameters // parameters, yet there is no key to inherit the parameters
// from. This is probably such a rare case that it is not worth // from. This is probably such a rare case that it is not worth
// trying to detect the situation earlier. // trying to detect the situation earlier.
cert.verify(anchor.getCAPublicKey(), cert.verify(anchor.getCAPublicKey(), buildParams.sigProvider());
buildParams.getSigProvider());
} catch (InvalidKeyException ike) { } catch (InvalidKeyException ike) {
if (debug != null) { if (debug != null) {
debug.println("ForwardBuilder.isPathCompleted() invalid " debug.println("ForwardBuilder.isPathCompleted() invalid "
+ "DSA key found"); + "DSA key found");
} }
continue; continue;
} catch (Exception e){ } catch (GeneralSecurityException e){
if (debug != null) { if (debug != null) {
debug.println("ForwardBuilder.isPathCompleted() " + debug.println("ForwardBuilder.isPathCompleted() " +
"unexpected exception"); "unexpected exception");
e.printStackTrace(); e.printStackTrace();
} }
continue; continue;
...@@ -908,8 +870,10 @@ class ForwardBuilder extends Builder { ...@@ -908,8 +870,10 @@ class ForwardBuilder extends Builder {
* @param cert the certificate to be added * @param cert the certificate to be added
* @param certPathList the certification path list * @param certPathList the certification path list
*/ */
@Override
void addCertToPath(X509Certificate cert, void addCertToPath(X509Certificate cert,
LinkedList<X509Certificate> certPathList) { LinkedList<X509Certificate> certPathList)
{
certPathList.addFirst(cert); certPathList.addFirst(cert);
} }
...@@ -917,6 +881,7 @@ class ForwardBuilder extends Builder { ...@@ -917,6 +881,7 @@ class ForwardBuilder extends Builder {
* *
* @param certPathList the certification path list * @param certPathList the certification path list
*/ */
@Override
void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) { void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
certPathList.removeFirst(); certPathList.removeFirst();
} }
......
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -34,7 +34,6 @@ import java.security.cert.X509Certificate; ...@@ -34,7 +34,6 @@ import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey; import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
...@@ -76,9 +75,6 @@ class ForwardState implements State { ...@@ -76,9 +75,6 @@ class ForwardState implements State {
/* Flag indicating if state is initial (path is just starting) */ /* Flag indicating if state is initial (path is just starting) */
private boolean init = true; private boolean init = true;
/* the checker used for revocation status */
public CrlRevocationChecker crlChecker;
/* The list of user-defined checkers that support forward checking */ /* The list of user-defined checkers that support forward checking */
ArrayList<PKIXCertPathChecker> forwardCheckers; ArrayList<PKIXCertPathChecker> forwardCheckers;
...@@ -93,6 +89,7 @@ class ForwardState implements State { ...@@ -93,6 +89,7 @@ class ForwardState implements State {
* *
* @return boolean flag indicating if the state is initial (just starting) * @return boolean flag indicating if the state is initial (just starting)
*/ */
@Override
public boolean isInitial() { public boolean isInitial() {
return init; return init;
} }
...@@ -104,6 +101,7 @@ class ForwardState implements State { ...@@ -104,6 +101,7 @@ class ForwardState implements State {
* @return boolean true if key needing to inherit parameters has been * @return boolean true if key needing to inherit parameters has been
* encountered; false otherwise. * encountered; false otherwise.
*/ */
@Override
public boolean keyParamsNeeded() { public boolean keyParamsNeeded() {
return keyParamsNeededFlag; return keyParamsNeededFlag;
} }
...@@ -111,23 +109,18 @@ class ForwardState implements State { ...@@ -111,23 +109,18 @@ class ForwardState implements State {
/** /**
* Display state for debugging purposes * Display state for debugging purposes
*/ */
@Override
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuilder sb = new StringBuilder();
try { sb.append("State [");
sb.append("State ["); sb.append("\n issuerDN of last cert: ").append(issuerDN);
sb.append("\n issuerDN of last cert: " + issuerDN); sb.append("\n traversedCACerts: ").append(traversedCACerts);
sb.append("\n traversedCACerts: " + traversedCACerts); sb.append("\n init: ").append(String.valueOf(init));
sb.append("\n init: " + String.valueOf(init)); sb.append("\n keyParamsNeeded: ").append
sb.append("\n keyParamsNeeded: " (String.valueOf(keyParamsNeededFlag));
+ String.valueOf(keyParamsNeededFlag)); sb.append("\n subjectNamesTraversed: \n").append
sb.append("\n subjectNamesTraversed: \n" + subjectNamesTraversed); (subjectNamesTraversed);
sb.append("]\n"); sb.append("]\n");
} catch (Exception e) {
if (debug != null) {
debug.println("ForwardState.toString() unexpected exception");
e.printStackTrace();
}
}
return sb.toString(); return sb.toString();
} }
...@@ -147,12 +140,10 @@ class ForwardState implements State { ...@@ -147,12 +140,10 @@ class ForwardState implements State {
* that supports forward checking and initialize the forwardCheckers * that supports forward checking and initialize the forwardCheckers
*/ */
forwardCheckers = new ArrayList<PKIXCertPathChecker>(); forwardCheckers = new ArrayList<PKIXCertPathChecker>();
if (certPathCheckers != null) { for (PKIXCertPathChecker checker : certPathCheckers) {
for (PKIXCertPathChecker checker : certPathCheckers) { if (checker.isForwardCheckingSupported()) {
if (checker.isForwardCheckingSupported()) { checker.init(true);
checker.init(true); forwardCheckers.add(checker);
forwardCheckers.add(checker);
}
} }
} }
...@@ -164,6 +155,7 @@ class ForwardState implements State { ...@@ -164,6 +155,7 @@ class ForwardState implements State {
* *
* @param cert the certificate which is used to update the state * @param cert the certificate which is used to update the state
*/ */
@Override
public void updateState(X509Certificate cert) public void updateState(X509Certificate cert)
throws CertificateException, IOException, CertPathValidatorException { throws CertificateException, IOException, CertPathValidatorException {
...@@ -208,13 +200,11 @@ class ForwardState implements State { ...@@ -208,13 +200,11 @@ class ForwardState implements State {
if (subjAltNameExt != null) { if (subjAltNameExt != null) {
GeneralNames gNames = subjAltNameExt.get( GeneralNames gNames = subjAltNameExt.get(
SubjectAlternativeNameExtension.SUBJECT_NAME); SubjectAlternativeNameExtension.SUBJECT_NAME);
for (Iterator<GeneralName> t = gNames.iterator(); for (GeneralName gName : gNames.names()) {
t.hasNext(); ) { subjectNamesTraversed.add(gName.getName());
GeneralNameInterface gName = t.next().getName();
subjectNamesTraversed.add(gName);
} }
} }
} catch (Exception e) { } catch (IOException e) {
if (debug != null) { if (debug != null) {
debug.println("ForwardState.updateState() unexpected " debug.println("ForwardState.updateState() unexpected "
+ "exception"); + "exception");
...@@ -236,6 +226,7 @@ class ForwardState implements State { ...@@ -236,6 +226,7 @@ class ForwardState implements State {
* because some of them will * because some of them will
* not have their contents modified by subsequent calls to updateState. * not have their contents modified by subsequent calls to updateState.
*/ */
@Override
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
public Object clone() { public Object clone() {
try { try {
......
/* /*
* Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -180,7 +180,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -180,7 +180,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
if (cert.equals(oldEntry)) { if (cert.equals(oldEntry)) {
return; return;
} }
List<X509Certificate> list = new ArrayList<X509Certificate>(2); List<X509Certificate> list = new ArrayList<>(2);
list.add(cert); list.add(cert);
list.add((X509Certificate)oldEntry); list.add((X509Certificate)oldEntry);
certSubjects.put(subject, list); certSubjects.put(subject, list);
...@@ -206,7 +206,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -206,7 +206,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
if (crl.equals(oldEntry)) { if (crl.equals(oldEntry)) {
return; return;
} }
List<X509CRL> list = new ArrayList<X509CRL>(2); List<X509CRL> list = new ArrayList<>(2);
list.add(crl); list.add(crl);
list.add((X509CRL)oldEntry); list.add((X509CRL)oldEntry);
crlIssuers.put(issuer, list); crlIssuers.put(issuer, list);
...@@ -234,19 +234,20 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -234,19 +234,20 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
* match the specified selector * match the specified selector
* @throws CertStoreException if an exception occurs * @throws CertStoreException if an exception occurs
*/ */
@Override
public Collection<? extends Certificate> engineGetCertificates(CertSelector selector) public Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
throws CertStoreException { throws CertStoreException {
// no selector means match all // no selector means match all
if (selector == null) { if (selector == null) {
Set<Certificate> matches = new HashSet<Certificate>(); Set<Certificate> matches = new HashSet<>();
matchX509Certs(new X509CertSelector(), matches); matchX509Certs(new X509CertSelector(), matches);
matches.addAll(otherCertificates); matches.addAll(otherCertificates);
return matches; return matches;
} }
if (selector instanceof X509CertSelector == false) { if (selector instanceof X509CertSelector == false) {
Set<Certificate> matches = new HashSet<Certificate>(); Set<Certificate> matches = new HashSet<>();
matchX509Certs(selector, matches); matchX509Certs(selector, matches);
for (Certificate cert : otherCertificates) { for (Certificate cert : otherCertificates) {
if (selector.match(cert)) { if (selector.match(cert)) {
...@@ -285,7 +286,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -285,7 +286,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
// See certSubjects javadoc. // See certSubjects javadoc.
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<X509Certificate> list = (List<X509Certificate>)entry; List<X509Certificate> list = (List<X509Certificate>)entry;
Set<X509Certificate> matches = new HashSet<X509Certificate>(16); Set<X509Certificate> matches = new HashSet<>(16);
for (X509Certificate cert : list) { for (X509Certificate cert : list) {
if (x509Selector.match(cert)) { if (x509Selector.match(cert)) {
matches.add(cert); matches.add(cert);
...@@ -295,7 +296,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -295,7 +296,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
} }
} }
// cannot use index, iterate all // cannot use index, iterate all
Set<Certificate> matches = new HashSet<Certificate>(16); Set<Certificate> matches = new HashSet<>(16);
matchX509Certs(x509Selector, matches); matchX509Certs(x509Selector, matches);
return matches; return matches;
} }
...@@ -338,18 +339,19 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -338,18 +339,19 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
* match the specified selector * match the specified selector
* @throws CertStoreException if an exception occurs * @throws CertStoreException if an exception occurs
*/ */
@Override
public Collection<CRL> engineGetCRLs(CRLSelector selector) public Collection<CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException { throws CertStoreException {
if (selector == null) { if (selector == null) {
Set<CRL> matches = new HashSet<CRL>(); Set<CRL> matches = new HashSet<>();
matchX509CRLs(new X509CRLSelector(), matches); matchX509CRLs(new X509CRLSelector(), matches);
matches.addAll(otherCRLs); matches.addAll(otherCRLs);
return matches; return matches;
} }
if (selector instanceof X509CRLSelector == false) { if (selector instanceof X509CRLSelector == false) {
Set<CRL> matches = new HashSet<CRL>(); Set<CRL> matches = new HashSet<>();
matchX509CRLs(selector, matches); matchX509CRLs(selector, matches);
for (CRL crl : otherCRLs) { for (CRL crl : otherCRLs) {
if (selector.match(crl)) { if (selector.match(crl)) {
...@@ -366,7 +368,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -366,7 +368,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
// see if the issuer is specified // see if the issuer is specified
Collection<X500Principal> issuers = x509Selector.getIssuers(); Collection<X500Principal> issuers = x509Selector.getIssuers();
if (issuers != null) { if (issuers != null) {
HashSet<CRL> matches = new HashSet<CRL>(16); HashSet<CRL> matches = new HashSet<>(16);
for (X500Principal issuer : issuers) { for (X500Principal issuer : issuers) {
Object entry = crlIssuers.get(issuer); Object entry = crlIssuers.get(issuer);
if (entry == null) { if (entry == null) {
...@@ -390,7 +392,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi { ...@@ -390,7 +392,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
return matches; return matches;
} }
// cannot use index, iterate all // cannot use index, iterate all
Set<CRL> matches = new HashSet<CRL>(16); Set<CRL> matches = new HashSet<>(16);
matchX509CRLs(x509Selector, matches); matchX509CRLs(x509Selector, matches);
return matches; return matches;
} }
......
/* /*
* Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,7 +30,7 @@ import java.security.cert.*; ...@@ -30,7 +30,7 @@ import java.security.cert.*;
import java.security.cert.PKIXReason; import java.security.cert.PKIXReason;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.PKIXExtensions; import static sun.security.x509.PKIXExtensions.*;
/** /**
* KeyChecker is a <code>PKIXCertPathChecker</code> that checks that the * KeyChecker is a <code>PKIXCertPathChecker</code> that checks that the
...@@ -45,33 +45,29 @@ import sun.security.x509.PKIXExtensions; ...@@ -45,33 +45,29 @@ import sun.security.x509.PKIXExtensions;
class KeyChecker extends PKIXCertPathChecker { class KeyChecker extends PKIXCertPathChecker {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
// the index of keyCertSign in the boolean KeyUsage array
private static final int keyCertSign = 5;
private final int certPathLen; private final int certPathLen;
private CertSelector targetConstraints; private final CertSelector targetConstraints;
private int remainingCerts; private int remainingCerts;
private Set<String> supportedExts; private Set<String> supportedExts;
/** /**
* Default Constructor * Creates a KeyChecker.
* *
* @param certPathLen allowable cert path length * @param certPathLen allowable cert path length
* @param targetCertSel a CertSelector object specifying the constraints * @param targetCertSel a CertSelector object specifying the constraints
* on the target certificate * on the target certificate
*/ */
KeyChecker(int certPathLen, CertSelector targetCertSel) KeyChecker(int certPathLen, CertSelector targetCertSel) {
throws CertPathValidatorException
{
this.certPathLen = certPathLen; this.certPathLen = certPathLen;
this.targetConstraints = targetCertSel; this.targetConstraints = targetCertSel;
init(false);
} }
/** /**
* Initializes the internal state of the checker from parameters * Initializes the internal state of the checker from parameters
* specified in the constructor * specified in the constructor
*/ */
@Override
public void init(boolean forward) throws CertPathValidatorException { public void init(boolean forward) throws CertPathValidatorException {
if (!forward) { if (!forward) {
remainingCerts = certPathLen; remainingCerts = certPathLen;
...@@ -81,16 +77,18 @@ class KeyChecker extends PKIXCertPathChecker { ...@@ -81,16 +77,18 @@ class KeyChecker extends PKIXCertPathChecker {
} }
} }
public final boolean isForwardCheckingSupported() { @Override
public boolean isForwardCheckingSupported() {
return false; return false;
} }
@Override
public Set<String> getSupportedExtensions() { public Set<String> getSupportedExtensions() {
if (supportedExts == null) { if (supportedExts == null) {
supportedExts = new HashSet<String>(); supportedExts = new HashSet<String>(3);
supportedExts.add(PKIXExtensions.KeyUsage_Id.toString()); supportedExts.add(KeyUsage_Id.toString());
supportedExts.add(PKIXExtensions.ExtendedKeyUsage_Id.toString()); supportedExts.add(ExtendedKeyUsage_Id.toString());
supportedExts.add(PKIXExtensions.SubjectAlternativeName_Id.toString()); supportedExts.add(SubjectAlternativeName_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts); supportedExts = Collections.unmodifiableSet(supportedExts);
} }
return supportedExts; return supportedExts;
...@@ -102,20 +100,20 @@ class KeyChecker extends PKIXCertPathChecker { ...@@ -102,20 +100,20 @@ class KeyChecker extends PKIXCertPathChecker {
* *
* @param cert the Certificate * @param cert the Certificate
* @param unresolvedCritExts the unresolved critical extensions * @param unresolvedCritExts the unresolved critical extensions
* @exception CertPathValidatorException Exception thrown if certificate * @throws CertPathValidatorException if certificate does not verify
* does not verify
*/ */
@Override
public void check(Certificate cert, Collection<String> unresCritExts) public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException throws CertPathValidatorException
{ {
X509Certificate currCert = (X509Certificate) cert; X509Certificate currCert = (X509Certificate)cert;
remainingCerts--; remainingCerts--;
// if final certificate, check that target constraints are satisfied // if final certificate, check that target constraints are satisfied
if (remainingCerts == 0) { if (remainingCerts == 0) {
if ((targetConstraints != null) && if (targetConstraints != null &&
(targetConstraints.match(currCert) == false)) { targetConstraints.match(currCert) == false) {
throw new CertPathValidatorException("target certificate " + throw new CertPathValidatorException("target certificate " +
"constraints check failed"); "constraints check failed");
} }
...@@ -126,25 +124,26 @@ class KeyChecker extends PKIXCertPathChecker { ...@@ -126,25 +124,26 @@ class KeyChecker extends PKIXCertPathChecker {
// remove the extensions that we have checked // remove the extensions that we have checked
if (unresCritExts != null && !unresCritExts.isEmpty()) { if (unresCritExts != null && !unresCritExts.isEmpty()) {
unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString()); unresCritExts.remove(KeyUsage_Id.toString());
unresCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString()); unresCritExts.remove(ExtendedKeyUsage_Id.toString());
unresCritExts.remove( unresCritExts.remove(SubjectAlternativeName_Id.toString());
PKIXExtensions.SubjectAlternativeName_Id.toString());
} }
} }
// the index of keyCertSign in the boolean KeyUsage array
private static final int KEY_CERT_SIGN = 5;
/** /**
* Static method to verify that the key usage and extended key usage * Verifies the key usage extension in a CA cert.
* extension in a CA cert. The key usage extension, if present, must * The key usage extension, if present, must assert the keyCertSign bit.
* assert the keyCertSign bit. The extended key usage extension, if * The extended key usage extension is not checked (see CR 4776794 for
* present, must include anyExtendedKeyUsage. * more information).
*/ */
static void verifyCAKeyUsage(X509Certificate cert) static void verifyCAKeyUsage(X509Certificate cert)
throws CertPathValidatorException { throws CertPathValidatorException {
String msg = "CA key usage"; String msg = "CA key usage";
if (debug != null) { if (debug != null) {
debug.println("KeyChecker.verifyCAKeyUsage() ---checking " + msg debug.println("KeyChecker.verifyCAKeyUsage() ---checking " + msg
+ "..."); + "...");
} }
boolean[] keyUsageBits = cert.getKeyUsage(); boolean[] keyUsageBits = cert.getKeyUsage();
...@@ -156,7 +155,7 @@ class KeyChecker extends PKIXCertPathChecker { ...@@ -156,7 +155,7 @@ class KeyChecker extends PKIXCertPathChecker {
} }
// throw an exception if the keyCertSign bit is not set // throw an exception if the keyCertSign bit is not set
if (!keyUsageBits[keyCertSign]) { if (!keyUsageBits[KEY_CERT_SIGN]) {
throw new CertPathValidatorException throw new CertPathValidatorException
(msg + " check failed: keyCertSign bit is not set", null, (msg + " check failed: keyCertSign bit is not set", null,
null, -1, PKIXReason.INVALID_KEY_USAGE); null, -1, PKIXReason.INVALID_KEY_USAGE);
...@@ -164,7 +163,7 @@ class KeyChecker extends PKIXCertPathChecker { ...@@ -164,7 +163,7 @@ class KeyChecker extends PKIXCertPathChecker {
if (debug != null) { if (debug != null) {
debug.println("KeyChecker.verifyCAKeyUsage() " + msg debug.println("KeyChecker.verifyCAKeyUsage() " + msg
+ " verified."); + " verified.");
} }
} }
} }
/* /*
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -43,6 +43,7 @@ import java.util.Map; ...@@ -43,6 +43,7 @@ import java.util.Map;
import static sun.security.provider.certpath.OCSPResponse.*; import static sun.security.provider.certpath.OCSPResponse.*;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AccessDescription; import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension; import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.GeneralName; import sun.security.x509.GeneralName;
...@@ -62,6 +63,9 @@ import sun.security.x509.X509CertImpl; ...@@ -62,6 +63,9 @@ import sun.security.x509.X509CertImpl;
*/ */
public final class OCSP { public final class OCSP {
static final ObjectIdentifier NONCE_EXTENSION_OID =
ObjectIdentifier.newInternal(new int[]{ 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private static final int CONNECT_TIMEOUT = 15000; // 15 seconds private static final int CONNECT_TIMEOUT = 15000; // 15 seconds
...@@ -83,7 +87,7 @@ public final class OCSP { ...@@ -83,7 +87,7 @@ public final class OCSP {
* encoding the OCSP Request or validating the OCSP Response * encoding the OCSP Request or validating the OCSP Response
*/ */
public static RevocationStatus check(X509Certificate cert, public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert) X509Certificate issuerCert)
throws IOException, CertPathValidatorException { throws IOException, CertPathValidatorException {
CertId certId = null; CertId certId = null;
URI responderURI = null; URI responderURI = null;
...@@ -95,16 +99,13 @@ public final class OCSP { ...@@ -95,16 +99,13 @@ public final class OCSP {
("No OCSP Responder URI in certificate"); ("No OCSP Responder URI in certificate");
} }
certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
} catch (CertificateException ce) { } catch (CertificateException | IOException e) {
throw new CertPathValidatorException
("Exception while encoding OCSPRequest", ce);
} catch (IOException ioe) {
throw new CertPathValidatorException throw new CertPathValidatorException
("Exception while encoding OCSPRequest", ioe); ("Exception while encoding OCSPRequest", e);
} }
OCSPResponse ocspResponse = check(Collections.singletonList(certId), OCSPResponse ocspResponse = check(Collections.singletonList(certId),
responderURI, issuerCert, null); responderURI, issuerCert, null, Collections.<Extension>emptyList());
return (RevocationStatus) ocspResponse.getSingleResponse(certId); return (RevocationStatus)ocspResponse.getSingleResponse(certId);
} }
/** /**
...@@ -123,22 +124,34 @@ public final class OCSP { ...@@ -123,22 +124,34 @@ public final class OCSP {
* encoding the OCSP Request or validating the OCSP Response * encoding the OCSP Request or validating the OCSP Response
*/ */
public static RevocationStatus check(X509Certificate cert, public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert, URI responderURI, X509Certificate X509Certificate issuerCert,
responderCert, Date date) URI responderURI,
throws IOException, CertPathValidatorException { X509Certificate responderCert,
Date date)
throws IOException, CertPathValidatorException
{
return check(cert, issuerCert, responderURI, responderCert, date,
Collections.<Extension>emptyList());
}
// Called by com.sun.deploy.security.TrustDecider
public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert,
URI responderURI,
X509Certificate responderCert,
Date date, List<Extension> extensions)
throws IOException, CertPathValidatorException
{
CertId certId = null; CertId certId = null;
try { try {
X509CertImpl certImpl = X509CertImpl.toImpl(cert); X509CertImpl certImpl = X509CertImpl.toImpl(cert);
certId = new CertId(issuerCert, certImpl.getSerialNumberObject()); certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
} catch (CertificateException ce) { } catch (CertificateException | IOException e) {
throw new CertPathValidatorException throw new CertPathValidatorException
("Exception while encoding OCSPRequest", ce); ("Exception while encoding OCSPRequest", e);
} catch (IOException ioe) {
throw new CertPathValidatorException
("Exception while encoding OCSPRequest", ioe);
} }
OCSPResponse ocspResponse = check(Collections.singletonList(certId), OCSPResponse ocspResponse = check(Collections.singletonList(certId),
responderURI, responderCert, date); responderURI, responderCert, date, extensions);
return (RevocationStatus) ocspResponse.getSingleResponse(certId); return (RevocationStatus) ocspResponse.getSingleResponse(certId);
} }
...@@ -157,12 +170,14 @@ public final class OCSP { ...@@ -157,12 +170,14 @@ public final class OCSP {
* encoding the OCSP Request or validating the OCSP Response * encoding the OCSP Request or validating the OCSP Response
*/ */
static OCSPResponse check(List<CertId> certIds, URI responderURI, static OCSPResponse check(List<CertId> certIds, URI responderURI,
X509Certificate responderCert, Date date) X509Certificate responderCert, Date date,
throws IOException, CertPathValidatorException { List<Extension> extensions)
throws IOException, CertPathValidatorException
{
byte[] bytes = null; byte[] bytes = null;
OCSPRequest request = null;
try { try {
OCSPRequest request = new OCSPRequest(certIds); request = new OCSPRequest(certIds, extensions);
bytes = request.encodeBytes(); bytes = request.encodeBytes();
} catch (IOException ioe) { } catch (IOException ioe) {
throw new CertPathValidatorException throw new CertPathValidatorException
...@@ -214,6 +229,8 @@ public final class OCSP { ...@@ -214,6 +229,8 @@ public final class OCSP {
} }
} }
response = Arrays.copyOf(response, total); response = Arrays.copyOf(response, total);
} catch (IOException ioe) {
throw new NetworkFailureException(ioe);
} finally { } finally {
if (in != null) { if (in != null) {
try { try {
...@@ -233,33 +250,15 @@ public final class OCSP { ...@@ -233,33 +250,15 @@ public final class OCSP {
OCSPResponse ocspResponse = null; OCSPResponse ocspResponse = null;
try { try {
ocspResponse = new OCSPResponse(response, date, responderCert); ocspResponse = new OCSPResponse(response);
} catch (IOException ioe) { } catch (IOException ioe) {
// response decoding exception // response decoding exception
throw new CertPathValidatorException(ioe); throw new CertPathValidatorException(ioe);
} }
if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) {
throw new CertPathValidatorException
("OCSP response error: " + ocspResponse.getResponseStatus());
}
// Check that the response includes a response for all of the // verify the response
// certs that were supplied in the request ocspResponse.verify(certIds, responderCert, date, request.getNonce());
for (CertId certId : certIds) {
SingleResponse sr = ocspResponse.getSingleResponse(certId);
if (sr == null) {
if (debug != null) {
debug.println("No response found for CertId: " + certId);
}
throw new CertPathValidatorException(
"OCSP response does not include a response for a " +
"certificate supplied in the OCSP request");
}
if (debug != null) {
debug.println("Status of certificate (with serial number " +
certId.getSerialNumber() + ") is: " + sr.getCertStatus());
}
}
return ocspResponse; return ocspResponse;
} }
...@@ -271,6 +270,7 @@ public final class OCSP { ...@@ -271,6 +270,7 @@ public final class OCSP {
* @param cert the certificate * @param cert the certificate
* @return the URI of the OCSP Responder, or null if not specified * @return the URI of the OCSP Responder, or null if not specified
*/ */
// Called by com.sun.deploy.security.TrustDecider
public static URI getResponderURI(X509Certificate cert) { public static URI getResponderURI(X509Certificate cert) {
try { try {
return getResponderURI(X509CertImpl.toImpl(cert)); return getResponderURI(X509CertImpl.toImpl(cert));
...@@ -330,4 +330,12 @@ public final class OCSP { ...@@ -330,4 +330,12 @@ public final class OCSP {
*/ */
Map<String, Extension> getSingleExtensions(); Map<String, Extension> getSingleExtensions();
} }
static class NetworkFailureException extends CertPathValidatorException {
private static final long serialVersionUID = 0l;
private NetworkFailureException(IOException ioe) {
super(ioe);
}
}
} }
/*
* Copyright (c) 2003, 2011, 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;
import java.math.BigInteger;
import java.util.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.Security;
import java.security.cert.*;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.net.URI;
import java.net.URISyntaxException;
import javax.security.auth.x500.X500Principal;
import static sun.security.provider.certpath.OCSP.*;
import sun.security.util.Debug;
import sun.security.x509.*;
/**
* OCSPChecker is a <code>PKIXCertPathChecker</code> that uses the
* Online Certificate Status Protocol (OCSP) as specified in RFC 2560
* <a href="http://www.ietf.org/rfc/rfc2560.txt">
* http://www.ietf.org/rfc/rfc2560.txt</a>.
*
* @author Ram Marti
*/
class OCSPChecker extends PKIXCertPathChecker {
static final String OCSP_ENABLE_PROP = "ocsp.enable";
static final String OCSP_URL_PROP = "ocsp.responderURL";
static final String OCSP_CERT_SUBJECT_PROP =
"ocsp.responderCertSubjectName";
static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName";
static final String OCSP_CERT_NUMBER_PROP =
"ocsp.responderCertSerialNumber";
private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
private static final Debug DEBUG = Debug.getInstance("certpath");
private static final boolean dump = false;
private int remainingCerts;
private X509Certificate[] certs;
private CertPath cp;
private PKIXParameters pkixParams;
private boolean onlyEECert = false;
/**
* Default Constructor
*
* @param certPath the X509 certification path
* @param pkixParams the input PKIX parameter set
* @throws CertPathValidatorException if OCSPChecker can not be created
*/
OCSPChecker(CertPath certPath, PKIXParameters pkixParams)
throws CertPathValidatorException {
this(certPath, pkixParams, false);
}
OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert)
throws CertPathValidatorException {
this.cp = certPath;
this.pkixParams = pkixParams;
this.onlyEECert = onlyEECert;
List<? extends Certificate> tmp = cp.getCertificates();
certs = tmp.toArray(new X509Certificate[tmp.size()]);
init(false);
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor
*/
@Override
public void init(boolean forward) throws CertPathValidatorException {
if (!forward) {
remainingCerts = certs.length + 1;
} else {
throw new CertPathValidatorException(
"Forward checking not supported");
}
}
@Override public boolean isForwardCheckingSupported() {
return false;
}
@Override public Set<String> getSupportedExtensions() {
return Collections.<String>emptySet();
}
/**
* Sends an OCSPRequest for the certificate to the OCSP Server and
* processes the response back from the OCSP Server.
*
* @param cert the Certificate
* @param unresolvedCritExts the unresolved critical extensions
* @exception CertPathValidatorException Exception is thrown if the
* certificate has been revoked.
*/
@Override
public void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException {
// Decrement the certificate counter
remainingCerts--;
X509CertImpl currCertImpl = null;
try {
currCertImpl = X509CertImpl.toImpl((X509Certificate)cert);
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
}
if (onlyEECert && currCertImpl.getBasicConstraints() != -1) {
if (DEBUG != null) {
DEBUG.println("Skipping revocation check, not end entity cert");
}
return;
}
/*
* OCSP security property values, in the following order:
* 1. ocsp.responderURL
* 2. ocsp.responderCertSubjectName
* 3. ocsp.responderCertIssuerName
* 4. ocsp.responderCertSerialNumber
*/
// should cache these properties to avoid calling every time?
String[] properties = getOCSPProperties();
// Check whether OCSP is feasible before seeking cert information
URI uri = getOCSPServerURI(currCertImpl, properties[0]);
// When responder's subject name is set then the issuer/serial
// properties are ignored
X500Principal responderSubjectName = null;
X500Principal responderIssuerName = null;
BigInteger responderSerialNumber = null;
if (properties[1] != null) {
responderSubjectName = new X500Principal(properties[1]);
} else if (properties[2] != null && properties[3] != null) {
responderIssuerName = new X500Principal(properties[2]);
// remove colon or space separators
String value = stripOutSeparators(properties[3]);
responderSerialNumber = new BigInteger(value, 16);
} else if (properties[2] != null || properties[3] != null) {
throw new CertPathValidatorException(
"Must specify both ocsp.responderCertIssuerName and " +
"ocsp.responderCertSerialNumber properties");
}
// If the OCSP responder cert properties are set then the
// identified cert must be located in the trust anchors or
// in the cert stores.
boolean seekResponderCert = false;
if (responderSubjectName != null || responderIssuerName != null) {
seekResponderCert = true;
}
// Set the issuer certificate to the next cert in the chain
// (unless we're processing the final cert).
X509Certificate issuerCert = null;
boolean seekIssuerCert = true;
X509Certificate responderCert = null;
if (remainingCerts < certs.length) {
issuerCert = certs[remainingCerts];
seekIssuerCert = false; // done
// By default, the OCSP responder's cert is the same as the
// issuer of the cert being validated.
if (!seekResponderCert) {
responderCert = issuerCert;
if (DEBUG != null) {
DEBUG.println("Responder's certificate is the same " +
"as the issuer of the certificate being validated");
}
}
}
// Check anchor certs for:
// - the issuer cert (of the cert being validated)
// - the OCSP responder's cert
if (seekIssuerCert || seekResponderCert) {
if (DEBUG != null && seekResponderCert) {
DEBUG.println("Searching trust anchors for responder's " +
"certificate");
}
// Extract the anchor certs
Iterator<TrustAnchor> anchors
= pkixParams.getTrustAnchors().iterator();
if (!anchors.hasNext()) {
throw new CertPathValidatorException(
"Must specify at least one trust anchor");
}
X500Principal certIssuerName =
currCertImpl.getIssuerX500Principal();
while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) {
TrustAnchor anchor = anchors.next();
X509Certificate anchorCert = anchor.getTrustedCert();
X500Principal anchorSubjectName =
anchorCert.getSubjectX500Principal();
if (dump) {
System.out.println("Issuer DN is " + certIssuerName);
System.out.println("Subject DN is " + anchorSubjectName);
}
// Check if anchor cert is the issuer cert
if (seekIssuerCert &&
certIssuerName.equals(anchorSubjectName)) {
issuerCert = anchorCert;
seekIssuerCert = false; // done
// By default, the OCSP responder's cert is the same as
// the issuer of the cert being validated.
if (!seekResponderCert && responderCert == null) {
responderCert = anchorCert;
if (DEBUG != null) {
DEBUG.println("Responder's certificate is the" +
" same as the issuer of the certificate " +
"being validated");
}
}
}
// Check if anchor cert is the responder cert
if (seekResponderCert) {
// Satisfy the responder subject name property only, or
// satisfy the responder issuer name and serial number
// properties only
if ((responderSubjectName != null &&
responderSubjectName.equals(anchorSubjectName)) ||
(responderIssuerName != null &&
responderSerialNumber != null &&
responderIssuerName.equals(
anchorCert.getIssuerX500Principal()) &&
responderSerialNumber.equals(
anchorCert.getSerialNumber()))) {
responderCert = anchorCert;
seekResponderCert = false; // done
}
}
}
if (issuerCert == null) {
throw new CertPathValidatorException(
"No trusted certificate for " + currCertImpl.getIssuerDN());
}
// Check cert stores if responder cert has not yet been found
if (seekResponderCert) {
if (DEBUG != null) {
DEBUG.println("Searching cert stores for responder's " +
"certificate");
}
X509CertSelector filter = null;
if (responderSubjectName != null) {
filter = new X509CertSelector();
filter.setSubject(responderSubjectName);
} else if (responderIssuerName != null &&
responderSerialNumber != null) {
filter = new X509CertSelector();
filter.setIssuer(responderIssuerName);
filter.setSerialNumber(responderSerialNumber);
}
if (filter != null) {
List<CertStore> certStores = pkixParams.getCertStores();
for (CertStore certStore : certStores) {
Iterator<? extends Certificate> i = null;
try {
i = certStore.getCertificates(filter).iterator();
} catch (CertStoreException cse) {
// ignore and try next certStore
if (DEBUG != null) {
DEBUG.println("CertStore exception:" + cse);
}
continue;
}
if (i.hasNext()) {
responderCert = (X509Certificate) i.next();
seekResponderCert = false; // done
break;
}
}
}
}
}
// Could not find the certificate identified in the OCSP properties
if (seekResponderCert) {
throw new CertPathValidatorException(
"Cannot find the responder's certificate " +
"(set using the OCSP security properties).");
}
// The algorithm constraints of the OCSP trusted responder certificate
// does not need to be checked in this code. The constraints will be
// checked when the responder's certificate is validated.
CertId certId = null;
OCSPResponse response = null;
try {
certId = new CertId
(issuerCert, currCertImpl.getSerialNumberObject());
response = OCSP.check(Collections.singletonList(certId), uri,
responderCert, pkixParams.getDate());
} catch (Exception e) {
if (e instanceof CertPathValidatorException) {
throw (CertPathValidatorException) e;
} else {
// Wrap exceptions in CertPathValidatorException so that
// we can fallback to CRLs, if enabled.
throw new CertPathValidatorException(e);
}
}
RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId);
RevocationStatus.CertStatus certStatus = rs.getCertStatus();
if (certStatus == RevocationStatus.CertStatus.REVOKED) {
Throwable t = new CertificateRevokedException(
rs.getRevocationTime(), rs.getRevocationReason(),
responderCert.getSubjectX500Principal(),
rs.getSingleExtensions());
throw new CertPathValidatorException(t.getMessage(), t,
null, -1, BasicReason.REVOKED);
} else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
throw new CertPathValidatorException(
"Certificate's revocation status is unknown", null, cp,
remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
/*
* The OCSP security property values are in the following order:
* 1. ocsp.responderURL
* 2. ocsp.responderCertSubjectName
* 3. ocsp.responderCertIssuerName
* 4. ocsp.responderCertSerialNumber
*/
private static URI getOCSPServerURI(X509CertImpl currCertImpl,
String responderURL) throws CertPathValidatorException {
if (responderURL != null) {
try {
return new URI(responderURL);
} catch (URISyntaxException e) {
throw new CertPathValidatorException(e);
}
}
// Examine the certificate's AuthorityInfoAccess extension
AuthorityInfoAccessExtension aia =
currCertImpl.getAuthorityInfoAccessExtension();
if (aia == null) {
throw new CertPathValidatorException(
"Must specify the location of an OCSP Responder");
}
List<AccessDescription> descriptions = aia.getAccessDescriptions();
for (AccessDescription description : descriptions) {
if (description.getAccessMethod().equals((Object)
AccessDescription.Ad_OCSP_Id)) {
GeneralName generalName = description.getAccessLocation();
if (generalName.getType() == GeneralNameInterface.NAME_URI) {
URIName uri = (URIName) generalName.getName();
return uri.getURI();
}
}
}
throw new CertPathValidatorException(
"Cannot find the location of the OCSP Responder");
}
/*
* Retrieves the values of the OCSP security properties.
*/
private static String[] getOCSPProperties() {
final String[] properties = new String[4];
AccessController.doPrivileged(
new PrivilegedAction<Void>() {
public Void run() {
properties[0] = Security.getProperty(OCSP_URL_PROP);
properties[1] =
Security.getProperty(OCSP_CERT_SUBJECT_PROP);
properties[2] =
Security.getProperty(OCSP_CERT_ISSUER_PROP);
properties[3] =
Security.getProperty(OCSP_CERT_NUMBER_PROP);
return null;
}
});
return properties;
}
/*
* Removes any non-hexadecimal characters from a string.
*/
private static String stripOutSeparators(String value) {
char[] chars = value.toCharArray();
StringBuilder hexNumber = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (HEX_DIGITS.indexOf(chars[i]) != -1) {
hexNumber.append(chars[i]);
}
}
return hexNumber.toString();
}
}
/* /*
* Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,8 +26,10 @@ ...@@ -26,8 +26,10 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.io.IOException; import java.io.IOException;
import java.security.cert.Extension;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import sun.misc.HexDumpEncoder; import sun.misc.HexDumpEncoder;
import sun.security.util.*; import sun.security.util.*;
...@@ -74,22 +76,29 @@ import sun.security.util.*; ...@@ -74,22 +76,29 @@ import sun.security.util.*;
class OCSPRequest { class OCSPRequest {
private static final Debug debug = Debug.getInstance("certpath");
private static final boolean dump = false; private static final boolean dump = false;
// List of request CertIds // List of request CertIds
private final List<CertId> certIds; private final List<CertId> certIds;
private final List<Extension> extensions;
private byte[] nonce;
/* /*
* Constructs an OCSPRequest. This constructor is used * Constructs an OCSPRequest. This constructor is used
* to construct an unsigned OCSP Request for a single user cert. * to construct an unsigned OCSP Request for a single user cert.
*/ */
OCSPRequest(CertId certId) { OCSPRequest(CertId certId) {
this.certIds = Collections.singletonList(certId); this(Collections.singletonList(certId));
} }
OCSPRequest(List<CertId> certIds) { OCSPRequest(List<CertId> certIds) {
this.certIds = certIds; this.certIds = certIds;
this.extensions = Collections.<Extension>emptyList();
}
OCSPRequest(List<CertId> certIds, List<Extension> extensions) {
this.certIds = certIds;
this.extensions = extensions;
} }
byte[] encodeBytes() throws IOException { byte[] encodeBytes() throws IOException {
...@@ -104,7 +113,20 @@ class OCSPRequest { ...@@ -104,7 +113,20 @@ class OCSPRequest {
} }
tmp.write(DerValue.tag_Sequence, requestsOut); tmp.write(DerValue.tag_Sequence, requestsOut);
// No extensions supported if (!extensions.isEmpty()) {
DerOutputStream extOut = new DerOutputStream();
for (Extension ext : extensions) {
ext.encode(extOut);
if (ext.getId().equals(OCSP.NONCE_EXTENSION_OID.toString())) {
nonce = ext.getValue();
}
}
DerOutputStream extsOut = new DerOutputStream();
extsOut.write(DerValue.tag_Sequence, extOut);
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte)2), extsOut);
}
DerOutputStream tbsRequest = new DerOutputStream(); DerOutputStream tbsRequest = new DerOutputStream();
tbsRequest.write(DerValue.tag_Sequence, tmp); tbsRequest.write(DerValue.tag_Sequence, tmp);
...@@ -126,4 +148,8 @@ class OCSPRequest { ...@@ -126,4 +148,8 @@ class OCSPRequest {
List<CertId> getCertIds() { List<CertId> getCertIds() {
return certIds; return certIds;
} }
byte[] getNonce() {
return nonce;
}
} }
/* /*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -33,11 +33,15 @@ import java.security.cert.CertPathValidatorException; ...@@ -33,11 +33,15 @@ import java.security.cert.CertPathValidatorException;
import java.security.cert.CRLReason; import java.security.cert.CRLReason;
import java.security.cert.TrustAnchor; import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.security.auth.x500.X500Principal;
import sun.misc.HexDumpEncoder; import sun.misc.HexDumpEncoder;
import sun.security.x509.*; import sun.security.x509.*;
import sun.security.util.*; import sun.security.util.*;
...@@ -125,13 +129,10 @@ public final class OCSPResponse { ...@@ -125,13 +129,10 @@ public final class OCSPResponse {
}; };
private static ResponseStatus[] rsvalues = ResponseStatus.values(); private static ResponseStatus[] rsvalues = ResponseStatus.values();
private static final Debug DEBUG = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private static final boolean dump = false; private static final boolean dump = false;
private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID = private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1}); ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID =
ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
private static final int CERT_STATUS_GOOD = 0; private static final int CERT_STATUS_GOOD = 0;
private static final int CERT_STATUS_REVOKED = 1; private static final int CERT_STATUS_REVOKED = 1;
private static final int CERT_STATUS_UNKNOWN = 2; private static final int CERT_STATUS_UNKNOWN = 2;
...@@ -143,9 +144,6 @@ public final class OCSPResponse { ...@@ -143,9 +144,6 @@ public final class OCSPResponse {
// Object identifier for the OCSPSigning key purpose // Object identifier for the OCSPSigning key purpose
private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9"; private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
private final ResponseStatus responseStatus;
private final Map<CertId, SingleResponse> singleResponseMap;
// Maximum clock skew in milliseconds (15 minutes) allowed when checking // Maximum clock skew in milliseconds (15 minutes) allowed when checking
// validity of OCSP responses // validity of OCSP responses
private static final long MAX_CLOCK_SKEW = 900000; private static final long MAX_CLOCK_SKEW = 900000;
...@@ -153,14 +151,20 @@ public final class OCSPResponse { ...@@ -153,14 +151,20 @@ public final class OCSPResponse {
// an array of all of the CRLReasons (used in SingleResponse) // an array of all of the CRLReasons (used in SingleResponse)
private static CRLReason[] values = CRLReason.values(); private static CRLReason[] values = CRLReason.values();
private final ResponseStatus responseStatus;
private final Map<CertId, SingleResponse> singleResponseMap;
private final List<X509CertImpl> certs;
private final AlgorithmId sigAlgId;
private final byte[] signature;
private final byte[] tbsResponseData;
private final X500Principal responderName;
private final byte[] responderKey;
private final byte[] responseNonce;
/* /*
* Create an OCSP response from its ASN.1 DER encoding. * Create an OCSP response from its ASN.1 DER encoding.
*/ */
OCSPResponse(byte[] bytes, Date dateCheckedAgainst, OCSPResponse(byte[] bytes) throws IOException {
X509Certificate responderCert)
throws IOException, CertPathValidatorException {
// OCSPResponse
if (dump) { if (dump) {
HexDumpEncoder hexEnc = new HexDumpEncoder(); HexDumpEncoder hexEnc = new HexDumpEncoder();
System.out.println("OCSPResponse bytes are..."); System.out.println("OCSPResponse bytes are...");
...@@ -181,12 +185,19 @@ public final class OCSPResponse { ...@@ -181,12 +185,19 @@ public final class OCSPResponse {
// unspecified responseStatus // unspecified responseStatus
throw new IOException("Unknown OCSPResponse status: " + status); throw new IOException("Unknown OCSPResponse status: " + status);
} }
if (DEBUG != null) { if (debug != null) {
DEBUG.println("OCSP response status: " + responseStatus); debug.println("OCSP response status: " + responseStatus);
} }
if (responseStatus != ResponseStatus.SUCCESSFUL) { if (responseStatus != ResponseStatus.SUCCESSFUL) {
// no need to continue, responseBytes are not set. // no need to continue, responseBytes are not set.
singleResponseMap = Collections.emptyMap(); singleResponseMap = Collections.emptyMap();
certs = Collections.<X509CertImpl>emptyList();
sigAlgId = null;
signature = null;
tbsResponseData = null;
responderName = null;
responderKey = null;
responseNonce = null;
return; return;
} }
...@@ -206,15 +217,15 @@ public final class OCSPResponse { ...@@ -206,15 +217,15 @@ public final class OCSPResponse {
derIn = tmp.data; derIn = tmp.data;
ObjectIdentifier responseType = derIn.getOID(); ObjectIdentifier responseType = derIn.getOID();
if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) { if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) {
if (DEBUG != null) { if (debug != null) {
DEBUG.println("OCSP response type: basic"); debug.println("OCSP response type: basic");
} }
} else { } else {
if (DEBUG != null) { if (debug != null) {
DEBUG.println("OCSP response type: " + responseType); debug.println("OCSP response type: " + responseType);
} }
throw new IOException("Unsupported OCSP response type: " + throw new IOException("Unsupported OCSP response type: " +
responseType); responseType);
} }
// BasicOCSPResponse // BasicOCSPResponse
...@@ -229,7 +240,7 @@ public final class OCSPResponse { ...@@ -229,7 +240,7 @@ public final class OCSPResponse {
DerValue responseData = seqTmp[0]; DerValue responseData = seqTmp[0];
// Need the DER encoded ResponseData to verify the signature later // Need the DER encoded ResponseData to verify the signature later
byte[] responseDataDer = seqTmp[0].toByteArray(); tbsResponseData = seqTmp[0].toByteArray();
// tbsResponseData // tbsResponseData
if (responseData.tag != DerValue.tag_Sequence) { if (responseData.tag != DerValue.tag_Sequence) {
...@@ -257,12 +268,15 @@ public final class OCSPResponse { ...@@ -257,12 +268,15 @@ public final class OCSPResponse {
// responderID // responderID
short tag = (byte)(seq.tag & 0x1f); short tag = (byte)(seq.tag & 0x1f);
if (tag == NAME_TAG) { if (tag == NAME_TAG) {
if (DEBUG != null) { responderName =
X500Name responderName = new X500Name(seq.getData()); new X500Principal(new ByteArrayInputStream(seq.toByteArray()));
DEBUG.println("OCSP Responder name: " + responderName); if (debug != null) {
debug.println("OCSP Responder name: " + responderName);
} }
responderKey = null;
} else if (tag == KEY_TAG) { } else if (tag == KEY_TAG) {
// Ignore, for now responderKey = seq.getOctetString();
responderName = null;
} else { } else {
throw new IOException("Bad encoding in responderID element of " + throw new IOException("Bad encoding in responderID element of " +
"OCSP response: expected ASN.1 context specific tag 0 or 1"); "OCSP response: expected ASN.1 context specific tag 0 or 1");
...@@ -270,57 +284,55 @@ public final class OCSPResponse { ...@@ -270,57 +284,55 @@ public final class OCSPResponse {
// producedAt // producedAt
seq = seqDerIn.getDerValue(); seq = seqDerIn.getDerValue();
if (DEBUG != null) { if (debug != null) {
Date producedAtDate = seq.getGeneralizedTime(); Date producedAtDate = seq.getGeneralizedTime();
DEBUG.println("OCSP response produced at: " + producedAtDate); debug.println("OCSP response produced at: " + producedAtDate);
} }
// responses // responses
DerValue[] singleResponseDer = seqDerIn.getSequence(1); DerValue[] singleResponseDer = seqDerIn.getSequence(1);
singleResponseMap singleResponseMap = new HashMap<>(singleResponseDer.length);
= new HashMap<CertId, SingleResponse>(singleResponseDer.length); if (debug != null) {
if (DEBUG != null) { debug.println("OCSP number of SingleResponses: "
DEBUG.println("OCSP number of SingleResponses: " + singleResponseDer.length);
+ singleResponseDer.length);
} }
for (int i = 0; i < singleResponseDer.length; i++) { for (int i = 0; i < singleResponseDer.length; i++) {
SingleResponse singleResponse SingleResponse singleResponse =
= new SingleResponse(singleResponseDer[i]); new SingleResponse(singleResponseDer[i]);
singleResponseMap.put(singleResponse.getCertId(), singleResponse); singleResponseMap.put(singleResponse.getCertId(), singleResponse);
} }
// responseExtensions // responseExtensions
byte[] nonce = null;
if (seqDerIn.available() > 0) { if (seqDerIn.available() > 0) {
seq = seqDerIn.getDerValue(); seq = seqDerIn.getDerValue();
if (seq.isContextSpecific((byte)1)) { if (seq.isContextSpecific((byte)1)) {
DerValue[] responseExtDer = seq.data.getSequence(3); DerValue[] responseExtDer = seq.data.getSequence(3);
for (int i = 0; i < responseExtDer.length; i++) { for (int i = 0; i < responseExtDer.length; i++) {
Extension responseExtension Extension ext = new Extension(responseExtDer[i]);
= new Extension(responseExtDer[i]); if (debug != null) {
if (DEBUG != null) { debug.println("OCSP extension: " + ext);
DEBUG.println("OCSP extension: " + responseExtension);
} }
if (responseExtension.getExtensionId().equals((Object) // Only the NONCE extension is recognized
OCSP_NONCE_EXTENSION_OID)) { if (ext.getExtensionId().equals((Object)
/* OCSP.NONCE_EXTENSION_OID))
ocspNonce = {
responseExtension[i].getExtensionValue(); nonce = ext.getExtensionValue();
*/ } else if (ext.isCritical()) {
} else if (responseExtension.isCritical()) {
throw new IOException( throw new IOException(
"Unsupported OCSP critical extension: " + "Unsupported OCSP critical extension: " +
responseExtension.getExtensionId()); ext.getExtensionId());
} }
} }
} }
} }
responseNonce = nonce;
// signatureAlgorithmId // signatureAlgorithmId
AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]); sigAlgId = AlgorithmId.parse(seqTmp[1]);
// signature // signature
byte[] signature = seqTmp[2].getBitString(); signature = seqTmp[2].getBitString();
X509CertImpl[] x509Certs = null;
// if seq[3] is available , then it is a sequence of certificates // if seq[3] is available , then it is a sequence of certificates
if (seqTmp.length > 3) { if (seqTmp.length > 3) {
...@@ -330,30 +342,59 @@ public final class OCSPResponse { ...@@ -330,30 +342,59 @@ public final class OCSPResponse {
throw new IOException("Bad encoding in certs element of " + throw new IOException("Bad encoding in certs element of " +
"OCSP response: expected ASN.1 context specific tag 0."); "OCSP response: expected ASN.1 context specific tag 0.");
} }
DerValue[] certs = seqCert.getData().getSequence(3); DerValue[] derCerts = seqCert.getData().getSequence(3);
x509Certs = new X509CertImpl[certs.length]; certs = new ArrayList<X509CertImpl>(derCerts.length);
try { try {
for (int i = 0; i < certs.length; i++) { for (int i = 0; i < derCerts.length; i++) {
x509Certs[i] = new X509CertImpl(certs[i].toByteArray()); certs.add(new X509CertImpl(derCerts[i].toByteArray()));
} }
} catch (CertificateException ce) { } catch (CertificateException ce) {
throw new IOException("Bad encoding in X509 Certificate", ce); throw new IOException("Bad encoding in X509 Certificate", ce);
} }
} else {
certs = Collections.<X509CertImpl>emptyList();
}
}
void verify(List<CertId> certIds, X509Certificate responderCert,
Date date, byte[] nonce)
throws CertPathValidatorException
{
if (responseStatus != ResponseStatus.SUCCESSFUL) {
throw new CertPathValidatorException
("OCSP response error: " + responseStatus);
}
// Check that the response includes a response for all of the
// certs that were supplied in the request
for (CertId certId : certIds) {
SingleResponse sr = getSingleResponse(certId);
if (sr == null) {
if (debug != null) {
debug.println("No response found for CertId: " + certId);
}
throw new CertPathValidatorException(
"OCSP response does not include a response for a " +
"certificate supplied in the OCSP request");
}
if (debug != null) {
debug.println("Status of certificate (with serial number " +
certId.getSerialNumber() + ") is: " + sr.getCertStatus());
}
} }
// Check whether the cert returned by the responder is trusted
if (x509Certs != null && x509Certs[0] != null) {
X509CertImpl cert = x509Certs[0];
// First check if the cert matches the responder cert which // Check whether the cert returned by the responder is trusted
// was set locally. if (!certs.isEmpty()) {
X509CertImpl cert = certs.get(0);
// First check if the cert matches the expected responder cert
if (cert.equals(responderCert)) { if (cert.equals(responderCert)) {
// cert is trusted, now verify the signed response // cert is trusted, now verify the signed response
// Next check if the cert was issued by the responder cert // Next check if the cert was issued by the responder cert
// which was set locally. // which was set locally.
} else if (cert.getIssuerX500Principal().equals( } else if (cert.getIssuerX500Principal().equals(
responderCert.getSubjectX500Principal())) { responderCert.getSubjectX500Principal())) {
// Check for the OCSPSigning key purpose // Check for the OCSPSigning key purpose
try { try {
...@@ -380,12 +421,12 @@ public final class OCSPResponse { ...@@ -380,12 +421,12 @@ public final class OCSPResponse {
// check the validity // check the validity
try { try {
if (dateCheckedAgainst == null) { if (date == null) {
cert.checkValidity(); cert.checkValidity();
} else { } else {
cert.checkValidity(dateCheckedAgainst); cert.checkValidity(date);
} }
} catch (GeneralSecurityException e) { } catch (CertificateException e) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Responder's certificate not within the " + "Responder's certificate not within the " +
"validity period", e); "validity period", e);
...@@ -401,8 +442,8 @@ public final class OCSPResponse { ...@@ -401,8 +442,8 @@ public final class OCSPResponse {
Extension noCheck = Extension noCheck =
cert.getExtension(PKIXExtensions.OCSPNoCheck_Id); cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
if (noCheck != null) { if (noCheck != null) {
if (DEBUG != null) { if (debug != null) {
DEBUG.println("Responder's certificate includes " + debug.println("Responder's certificate includes " +
"the extension id-pkix-ocsp-nocheck."); "the extension id-pkix-ocsp-nocheck.");
} }
} else { } else {
...@@ -433,15 +474,44 @@ public final class OCSPResponse { ...@@ -433,15 +474,44 @@ public final class OCSPResponse {
// "jdk.certpath.disabledAlgorithms". // "jdk.certpath.disabledAlgorithms".
AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId); AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
if (!verifyResponse(responseDataDer, responderCert, if (!verifySignature(responderCert)) {
sigAlgId, signature)) {
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Error verifying OCSP Responder's signature"); "Error verifying OCSP Response's signature");
} }
} else { } else {
// Need responder's cert in order to verify the signature // Need responder's cert in order to verify the signature
throw new CertPathValidatorException( throw new CertPathValidatorException(
"Unable to verify OCSP Responder's signature"); "Unable to verify OCSP Response's signature");
}
// Check freshness of OCSPResponse
if (nonce != null) {
if (responseNonce != null && !Arrays.equals(nonce, responseNonce)) {
throw new CertPathValidatorException("Nonces don't match");
}
}
long now = (date == null) ? System.currentTimeMillis() : date.getTime();
Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
for (SingleResponse sr : singleResponseMap.values()) {
if (debug != null) {
String until = "";
if (sr.nextUpdate != null) {
until = " until " + sr.nextUpdate;
}
debug.println("Response's validity interval is from " +
sr.thisUpdate + until);
}
// Check that the test date is within the validity interval
if ((sr.thisUpdate != null && nowPlusSkew.before(sr.thisUpdate)) ||
(sr.nextUpdate != null && nowMinusSkew.after(sr.nextUpdate)))
{
throw new CertPathValidatorException(
"Response is unreliable: its validity " +
"interval is out-of-date");
}
} }
} }
...@@ -456,34 +526,31 @@ public final class OCSPResponse { ...@@ -456,34 +526,31 @@ public final class OCSPResponse {
* Verify the signature of the OCSP response. * Verify the signature of the OCSP response.
* The responder's cert is implicitly trusted. * The responder's cert is implicitly trusted.
*/ */
private boolean verifyResponse(byte[] responseData, X509Certificate cert, private boolean verifySignature(X509Certificate cert)
AlgorithmId sigAlgId, byte[] signBytes)
throws CertPathValidatorException { throws CertPathValidatorException {
try { try {
Signature respSignature = Signature.getInstance(sigAlgId.getName()); Signature respSignature = Signature.getInstance(sigAlgId.getName());
respSignature.initVerify(cert); respSignature.initVerify(cert);
respSignature.update(responseData); respSignature.update(tbsResponseData);
if (respSignature.verify(signBytes)) { if (respSignature.verify(signature)) {
if (DEBUG != null) { if (debug != null) {
DEBUG.println("Verified signature of OCSP Responder"); debug.println("Verified signature of OCSP Response");
} }
return true; return true;
} else { } else {
if (DEBUG != null) { if (debug != null) {
DEBUG.println( debug.println(
"Error verifying signature of OCSP Responder"); "Error verifying signature of OCSP Response");
} }
return false; return false;
} }
} catch (InvalidKeyException ike) { } catch (InvalidKeyException | NoSuchAlgorithmException |
throw new CertPathValidatorException(ike); SignatureException e)
} catch (NoSuchAlgorithmException nsae) { {
throw new CertPathValidatorException(nsae); throw new CertPathValidatorException(e);
} catch (SignatureException se) {
throw new CertPathValidatorException(se);
} }
} }
...@@ -537,9 +604,9 @@ public final class OCSPResponse { ...@@ -537,9 +604,9 @@ public final class OCSPResponse {
revocationReason = CRLReason.UNSPECIFIED; revocationReason = CRLReason.UNSPECIFIED;
} }
// RevokedInfo // RevokedInfo
if (DEBUG != null) { if (debug != null) {
DEBUG.println("Revocation time: " + revocationTime); debug.println("Revocation time: " + revocationTime);
DEBUG.println("Revocation reason: " + revocationReason); debug.println("Revocation reason: " + revocationReason);
} }
} else { } else {
revocationTime = null; revocationTime = null;
...@@ -585,8 +652,8 @@ public final class OCSPResponse { ...@@ -585,8 +652,8 @@ public final class OCSPResponse {
(singleExtDer.length); (singleExtDer.length);
for (int i = 0; i < singleExtDer.length; i++) { for (int i = 0; i < singleExtDer.length; i++) {
Extension ext = new Extension(singleExtDer[i]); Extension ext = new Extension(singleExtDer[i]);
if (DEBUG != null) { if (debug != null) {
DEBUG.println("OCSP single extension: " + ext); debug.println("OCSP single extension: " + ext);
} }
// We don't support any extensions yet. Therefore, if it // We don't support any extensions yet. Therefore, if it
// is critical we must throw an exception because we // is critical we must throw an exception because we
...@@ -604,29 +671,6 @@ public final class OCSPResponse { ...@@ -604,29 +671,6 @@ public final class OCSPResponse {
} else { } else {
singleExtensions = Collections.emptyMap(); singleExtensions = Collections.emptyMap();
} }
long now = System.currentTimeMillis();
Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
if (DEBUG != null) {
String until = "";
if (nextUpdate != null) {
until = " until " + nextUpdate;
}
DEBUG.println("Response's validity interval is from " +
thisUpdate + until);
}
// Check that the test date is within the validity interval
if ((thisUpdate != null && nowPlusSkew.before(thisUpdate)) ||
(nextUpdate != null && nowMinusSkew.after(nextUpdate))) {
if (DEBUG != null) {
DEBUG.println("Response is unreliable: its validity " +
"interval is out-of-date");
}
throw new IOException("Response is unreliable: its validity " +
"interval is out-of-date");
}
} }
/* /*
......
/*
* Copyright (c) 2012, 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;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.cert.*;
import java.util.*;
import javax.security.auth.x500.X500Principal;
import sun.security.util.Debug;
/**
* Common utility methods and classes used by the PKIX CertPathValidator and
* CertPathBuilder implementation.
*/
class PKIX {
private static final Debug debug = Debug.getInstance("certpath");
private PKIX() { }
static ValidatorParams checkParams(CertPath cp, CertPathParameters params)
throws InvalidAlgorithmParameterException
{
if (!(params instanceof PKIXParameters)) {
throw new InvalidAlgorithmParameterException("inappropriate "
+ "params, must be an instance of PKIXParameters");
}
return new ValidatorParams(cp, (PKIXParameters)params);
}
static BuilderParams checkBuilderParams(CertPathParameters params)
throws InvalidAlgorithmParameterException
{
if (!(params instanceof PKIXBuilderParameters)) {
throw new InvalidAlgorithmParameterException("inappropriate "
+ "params, must be an instance of PKIXBuilderParameters");
}
return new BuilderParams((PKIXBuilderParameters)params);
}
/**
* PKIXParameters that are shared by the PKIX CertPathValidator
* implementation. Provides additional functionality and avoids
* unnecessary cloning.
*/
static class ValidatorParams {
private final PKIXParameters params;
private CertPath certPath;
private List<PKIXCertPathChecker> checkers;
private List<CertStore> stores;
private boolean gotDate;
private Date date;
private Set<String> policies;
private boolean gotConstraints;
private CertSelector constraints;
private Set<TrustAnchor> anchors;
private List<X509Certificate> certs;
ValidatorParams(CertPath cp, PKIXParameters params)
throws InvalidAlgorithmParameterException
{
this(params);
if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {
throw new InvalidAlgorithmParameterException("inappropriate "
+ "CertPath type specified, must be X.509 or X509");
}
this.certPath = cp;
}
ValidatorParams(PKIXParameters params)
throws InvalidAlgorithmParameterException
{
this.anchors = params.getTrustAnchors();
// Make sure that none of the trust anchors include name constraints
// (not supported).
for (TrustAnchor anchor : this.anchors) {
if (anchor.getNameConstraints() != null) {
throw new InvalidAlgorithmParameterException
("name constraints in trust anchor not supported");
}
}
this.params = params;
}
CertPath certPath() {
return certPath;
}
// called by CertPathBuilder after path has been built
void setCertPath(CertPath cp) {
this.certPath = cp;
}
List<X509Certificate> certificates() {
if (certs == null) {
if (certPath == null) {
certs = Collections.emptyList();
} else {
// Reverse the ordering for validation so that the target
// cert is the last certificate
@SuppressWarnings("unchecked")
List<X509Certificate> xc = new ArrayList<>
((List<X509Certificate>)certPath.getCertificates());
Collections.reverse(xc);
certs = xc;
}
}
return certs;
}
List<PKIXCertPathChecker> certPathCheckers() {
if (checkers == null)
checkers = params.getCertPathCheckers();
return checkers;
}
List<CertStore> certStores() {
if (stores == null)
stores = params.getCertStores();
return stores;
}
Date date() {
if (!gotDate) {
date = params.getDate();
if (date == null)
date = new Date();
gotDate = true;
}
return date;
}
Set<String> initialPolicies() {
if (policies == null)
policies = params.getInitialPolicies();
return policies;
}
CertSelector targetCertConstraints() {
if (!gotConstraints) {
constraints = params.getTargetCertConstraints();
gotConstraints = true;
}
return constraints;
}
Set<TrustAnchor> trustAnchors() {
return anchors;
}
boolean revocationEnabled() {
return params.isRevocationEnabled();
}
boolean policyMappingInhibited() {
return params.isPolicyMappingInhibited();
}
boolean explicitPolicyRequired() {
return params.isExplicitPolicyRequired();
}
boolean policyQualifiersRejected() {
return params.getPolicyQualifiersRejected();
}
String sigProvider() { return params.getSigProvider(); }
boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); }
// in rare cases we need access to the original params, for example
// in order to clone CertPathCheckers before building a new chain
PKIXParameters getPKIXParameters() {
return params;
}
}
static class BuilderParams extends ValidatorParams {
private PKIXBuilderParameters params;
private boolean buildForward = true;
private List<CertStore> stores;
private X500Principal targetSubject;
BuilderParams(PKIXBuilderParameters params)
throws InvalidAlgorithmParameterException
{
super(params);
checkParams(params);
}
private void checkParams(PKIXBuilderParameters params)
throws InvalidAlgorithmParameterException
{
CertSelector sel = targetCertConstraints();
if (!(sel instanceof X509CertSelector)) {
throw new InvalidAlgorithmParameterException("the "
+ "targetCertConstraints parameter must be an "
+ "X509CertSelector");
}
if (params instanceof SunCertPathBuilderParameters) {
buildForward =
((SunCertPathBuilderParameters)params).getBuildForward();
}
this.params = params;
this.targetSubject = getTargetSubject(
certStores(), (X509CertSelector)targetCertConstraints());
}
@Override List<CertStore> certStores() {
if (stores == null) {
// reorder CertStores so that local CertStores are tried first
stores = new ArrayList<>(params.getCertStores());
Collections.sort(stores, new CertStoreComparator());
}
return stores;
}
int maxPathLength() { return params.getMaxPathLength(); }
boolean buildForward() { return buildForward; }
PKIXBuilderParameters params() { return params; }
X500Principal targetSubject() { return targetSubject; }
/**
* Returns the target subject DN from the first X509Certificate that
* is fetched that matches the specified X509CertSelector.
*/
private static X500Principal getTargetSubject(List<CertStore> stores,
X509CertSelector sel)
throws InvalidAlgorithmParameterException
{
X500Principal subject = sel.getSubject();
if (subject != null) {
return subject;
}
X509Certificate cert = sel.getCertificate();
if (cert != null) {
subject = cert.getSubjectX500Principal();
}
if (subject != null) {
return subject;
}
for (CertStore store : stores) {
try {
Collection<? extends Certificate> certs =
(Collection<? extends Certificate>)
store.getCertificates(sel);
if (!certs.isEmpty()) {
X509Certificate xc =
(X509Certificate)certs.iterator().next();
return xc.getSubjectX500Principal();
}
} catch (CertStoreException e) {
// ignore but log it
if (debug != null) {
debug.println("BuilderParams.getTargetSubjectDN: " +
"non-fatal exception retrieving certs: " + e);
e.printStackTrace();
}
}
}
throw new InvalidAlgorithmParameterException
("Could not determine unique target subject");
}
}
/**
* Comparator that orders CertStores so that local CertStores come before
* remote CertStores.
*/
private static class CertStoreComparator implements Comparator<CertStore> {
@Override
public int compare(CertStore store1, CertStore store2) {
if (store1.getType().equals("Collection") ||
store1.getCertStoreParameters() instanceof
CollectionCertStoreParameters) {
return -1;
} else {
return 1;
}
}
}
}
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,55 +25,38 @@ ...@@ -25,55 +25,38 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.security.AccessController; import java.io.IOException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CertPath; import java.security.cert.*;
import java.security.cert.CertPathParameters; import java.util.*;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorSpi;
import java.security.cert.CertPathValidatorResult;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXCertPathValidatorResult;
import java.security.cert.PKIXParameters;
import java.security.cert.PKIXReason;
import java.security.cert.PolicyNode;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Collections;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
import sun.security.action.GetBooleanSecurityPropertyAction;
import sun.security.util.Debug;
import sun.security.provider.certpath.PKIX.ValidatorParams;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
import sun.security.util.Debug;
/** /**
* This class implements the PKIX validation algorithm for certification * This class implements the PKIX validation algorithm for certification
* paths consisting exclusively of <code>X509Certificates</code>. It uses * paths consisting exclusively of <code>X509Certificates</code>. It uses
* the specified input parameter set (which must be a * the specified input parameter set (which must be a
* <code>PKIXParameters</code> object) and signature provider (if any). * <code>PKIXParameters</code> object).
* *
* @since 1.4 * @since 1.4
* @author Yassir Elley * @author Yassir Elley
*/ */
public class PKIXCertPathValidator extends CertPathValidatorSpi { public final class PKIXCertPathValidator extends CertPathValidatorSpi {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private Date testDate;
private List<PKIXCertPathChecker> userCheckers;
private String sigProvider;
private BasicChecker basicChecker;
private boolean ocspEnabled = false;
private boolean onlyEECert = false;
/** /**
* Default constructor. * Default constructor.
*/ */
public PKIXCertPathValidator() {} public PKIXCertPathValidator() {}
@Override
public CertPathChecker engineGetRevocationChecker() {
return new RevocationChecker();
}
/** /**
* Validates a certification path consisting exclusively of * Validates a certification path consisting exclusively of
* <code>X509Certificate</code>s using the PKIX validation algorithm, * <code>X509Certificate</code>s using the PKIX validation algorithm,
...@@ -81,98 +64,70 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { ...@@ -81,98 +64,70 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
* The input parameter set must be a <code>PKIXParameters</code> object. * The input parameter set must be a <code>PKIXParameters</code> object.
* *
* @param cp the X509 certification path * @param cp the X509 certification path
* @param param the input PKIX parameter set * @param params the input PKIX parameter set
* @return the result * @return the result
* @exception CertPathValidatorException Exception thrown if cert path * @throws CertPathValidatorException if cert path does not validate.
* does not validate. * @throws InvalidAlgorithmParameterException if the specified
* @exception InvalidAlgorithmParameterException if the specified * parameters are inappropriate for this CertPathValidator
* parameters are inappropriate for this certification path validator
*/ */
@Override
public CertPathValidatorResult engineValidate(CertPath cp, public CertPathValidatorResult engineValidate(CertPath cp,
CertPathParameters param) CertPathParameters params)
throws CertPathValidatorException, InvalidAlgorithmParameterException throws CertPathValidatorException, InvalidAlgorithmParameterException
{
ValidatorParams valParams = PKIX.checkParams(cp, params);
return validate(valParams);
}
private static PKIXCertPathValidatorResult validate(ValidatorParams params)
throws CertPathValidatorException
{ {
if (debug != null) if (debug != null)
debug.println("PKIXCertPathValidator.engineValidate()..."); debug.println("PKIXCertPathValidator.engineValidate()...");
if (!(param instanceof PKIXParameters)) {
throw new InvalidAlgorithmParameterException("inappropriate "
+ "parameters, must be an instance of PKIXParameters");
}
if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {
throw new InvalidAlgorithmParameterException("inappropriate "
+ "certification path type specified, must be X.509 or X509");
}
PKIXParameters pkixParam = (PKIXParameters) param;
// Make sure that none of the trust anchors include name constraints
// (not supported).
Set<TrustAnchor> anchors = pkixParam.getTrustAnchors();
for (TrustAnchor anchor : anchors) {
if (anchor.getNameConstraints() != null) {
throw new InvalidAlgorithmParameterException
("name constraints in trust anchor not supported");
}
}
// the certpath which has been passed in (cp)
// has the target cert as the first certificate - we
// need to keep this cp so we can return it
// in case of an exception and for policy qualifier
// processing - however, for certpath validation,
// we need to create a reversed path, where we reverse the
// ordering so that the target cert is the last certificate
// Must copy elements of certList into a new modifiable List before
// calling Collections.reverse().
// If cp is not an X.509 or X509 certpath, an
// InvalidAlgorithmParameterException will have been thrown by now.
@SuppressWarnings("unchecked")
ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>
((List<X509Certificate>)cp.getCertificates());
if (debug != null) {
if (certList.isEmpty()) {
debug.println("PKIXCertPathValidator.engineValidate() "
+ "certList is empty");
}
debug.println("PKIXCertPathValidator.engineValidate() "
+ "reversing certpath...");
}
Collections.reverse(certList);
// now certList has the target cert as the last cert and we
// can proceed with normal validation
populateVariables(pkixParam);
// Retrieve the first certificate in the certpath // Retrieve the first certificate in the certpath
// (to be used later in pre-screening) // (to be used later in pre-screening)
X509Certificate firstCert = null; AdaptableX509CertSelector selector = null;
List<X509Certificate> certList = params.certificates();
if (!certList.isEmpty()) { if (!certList.isEmpty()) {
firstCert = certList.get(0); selector = new AdaptableX509CertSelector();
X509Certificate firstCert = certList.get(0);
// check trusted certificate's subject
selector.setSubject(firstCert.getIssuerX500Principal());
// check the validity period
selector.setValidityPeriod(firstCert.getNotBefore(),
firstCert.getNotAfter());
/*
* Facilitate certification path construction with authority
* key identifier and subject key identifier.
*/
try {
X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert);
selector.parseAuthorityKeyIdentifierExtension(
firstCertImpl.getAuthorityKeyIdentifierExtension());
} catch (CertificateException | IOException e) {
// ignore
}
} }
CertPathValidatorException lastException = null; CertPathValidatorException lastException = null;
// We iterate through the set of trust anchors until we find // We iterate through the set of trust anchors until we find
// one that works at which time we stop iterating // one that works at which time we stop iterating
for (TrustAnchor anchor : anchors) { for (TrustAnchor anchor : params.trustAnchors()) {
X509Certificate trustedCert = anchor.getTrustedCert(); X509Certificate trustedCert = anchor.getTrustedCert();
if (trustedCert != null) { if (trustedCert != null) {
if (debug != null) {
debug.println("PKIXCertPathValidator.engineValidate() "
+ "anchor.getTrustedCert() != null");
}
// if this trust anchor is not worth trying, // if this trust anchor is not worth trying,
// we move on to the next one // we move on to the next one
if (!isWorthTrying(trustedCert, firstCert)) { if (selector != null && !selector.match(trustedCert)) {
if (debug != null) {
debug.println("NO - don't try this trustedCert");
}
continue; continue;
} }
if (debug != null) { if (debug != null) {
debug.println("YES - try this trustedCert");
debug.println("anchor.getTrustedCert()." debug.println("anchor.getTrustedCert()."
+ "getSubjectX500Principal() = " + "getSubjectX500Principal() = "
+ trustedCert.getSubjectX500Principal()); + trustedCert.getSubjectX500Principal());
...@@ -185,14 +140,7 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { ...@@ -185,14 +140,7 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
} }
try { try {
PolicyNodeImpl rootNode = new PolicyNodeImpl(null, return validate(anchor, params);
PolicyChecker.ANY_POLICY, null, false,
Collections.singleton(PolicyChecker.ANY_POLICY), false);
PolicyNode policyTree =
doValidate(anchor, cp, certList, pkixParam, rootNode);
// if this anchor works, return success
return new PKIXCertPathValidatorResult(anchor, policyTree,
basicChecker.getPublicKey());
} catch (CertPathValidatorException cpe) { } catch (CertPathValidatorException cpe) {
// remember this exception // remember this exception
lastException = cpe; lastException = cpe;
...@@ -210,144 +158,59 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi { ...@@ -210,144 +158,59 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
null, null, -1, PKIXReason.NO_TRUST_ANCHOR); null, null, -1, PKIXReason.NO_TRUST_ANCHOR);
} }
/** private static PKIXCertPathValidatorResult validate(TrustAnchor anchor,
* Internal method to do some simple checks to see if a given cert is ValidatorParams params)
* worth trying to validate in the chain. throws CertPathValidatorException
*/
private boolean isWorthTrying(X509Certificate trustedCert,
X509Certificate firstCert) {
boolean worthy = false;
if (debug != null) {
debug.println("PKIXCertPathValidator.isWorthTrying() checking "
+ "if this trusted cert is worth trying ...");
}
if (firstCert == null) {
return true;
}
AdaptableX509CertSelector issuerSelector =
new AdaptableX509CertSelector();
// check trusted certificate's subject
issuerSelector.setSubject(firstCert.getIssuerX500Principal());
// check the validity period
issuerSelector.setValidityPeriod(firstCert.getNotBefore(),
firstCert.getNotAfter());
/*
* Facilitate certification path construction with authority
* key identifier and subject key identifier.
*/
try {
X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert);
issuerSelector.parseAuthorityKeyIdentifierExtension(
firstCertImpl.getAuthorityKeyIdentifierExtension());
worthy = issuerSelector.match(trustedCert);
} catch (Exception e) {
// It is not worth trying.
}
if (debug != null) {
if (worthy) {
debug.println("YES - try this trustedCert");
} else {
debug.println("NO - don't try this trustedCert");
}
}
return worthy;
}
/**
* Internal method to setup the internal state
*/
private void populateVariables(PKIXParameters pkixParam)
{ {
// default value for testDate is current time int certPathLen = params.certificates().size();
testDate = pkixParam.getDate();
if (testDate == null) {
testDate = new Date(System.currentTimeMillis());
}
userCheckers = pkixParam.getCertPathCheckers();
sigProvider = pkixParam.getSigProvider();
if (pkixParam.isRevocationEnabled()) { // create PKIXCertPathCheckers
// Examine OCSP security property List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
ocspEnabled = AccessController.doPrivileged(
new GetBooleanSecurityPropertyAction
(OCSPChecker.OCSP_ENABLE_PROP));
onlyEECert = AccessController.doPrivileged(
new GetBooleanSecurityPropertyAction
("com.sun.security.onlyCheckRevocationOfEECert"));
}
}
/**
* Internal method to actually validate a constructed path.
*
* @return the valid policy tree
*/
private PolicyNode doValidate(
TrustAnchor anchor, CertPath cpOriginal,
ArrayList<X509Certificate> certList, PKIXParameters pkixParam,
PolicyNodeImpl rootNode) throws CertPathValidatorException
{
int certPathLen = certList.size();
basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
KeyChecker keyChecker = new KeyChecker(certPathLen,
pkixParam.getTargetCertConstraints());
ConstraintsChecker constraintsChecker =
new ConstraintsChecker(certPathLen);
PolicyChecker policyChecker =
new PolicyChecker(pkixParam.getInitialPolicies(), certPathLen,
pkixParam.isExplicitPolicyRequired(),
pkixParam.isPolicyMappingInhibited(),
pkixParam.isAnyPolicyInhibited(),
pkixParam.getPolicyQualifiersRejected(),
rootNode);
ArrayList<PKIXCertPathChecker> certPathCheckers =
new ArrayList<PKIXCertPathChecker>();
// add standard checkers that we will be using // add standard checkers that we will be using
certPathCheckers.add(algorithmChecker); certPathCheckers.add(new AlgorithmChecker(anchor));
certPathCheckers.add(keyChecker); certPathCheckers.add(new KeyChecker(certPathLen,
certPathCheckers.add(constraintsChecker); params.targetCertConstraints()));
certPathCheckers.add(policyChecker); certPathCheckers.add(new ConstraintsChecker(certPathLen));
certPathCheckers.add(basicChecker); PolicyNodeImpl rootNode =
new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, false,
// only add a revocationChecker if revocation is enabled Collections.singleton(PolicyChecker.ANY_POLICY),
if (pkixParam.isRevocationEnabled()) { false);
PolicyChecker pc = new PolicyChecker(params.initialPolicies(),
// Use OCSP if it has been enabled certPathLen,
if (ocspEnabled) { params.explicitPolicyRequired(),
OCSPChecker ocspChecker = params.policyMappingInhibited(),
new OCSPChecker(cpOriginal, pkixParam, onlyEECert); params.anyPolicyInhibited(),
certPathCheckers.add(ocspChecker); params.policyQualifiersRejected(),
rootNode);
certPathCheckers.add(pc);
// default value for date is current time
BasicChecker bc = new BasicChecker(anchor, params.date(),
params.sigProvider(), false);
certPathCheckers.add(bc);
boolean revCheckerAdded = false;
List<PKIXCertPathChecker> checkers = params.certPathCheckers();
for (PKIXCertPathChecker checker : checkers) {
if (checker instanceof PKIXRevocationChecker) {
revCheckerAdded = true;
// if it's our own, initialize it
if (checker instanceof RevocationChecker)
((RevocationChecker)checker).init(anchor, params);
} }
// Always use CRLs
CrlRevocationChecker revocationChecker = new
CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert);
certPathCheckers.add(revocationChecker);
} }
// only add a RevocationChecker if revocation is enabled and
// a PKIXRevocationChecker has not already been added
if (params.revocationEnabled() && !revCheckerAdded) {
certPathCheckers.add(new RevocationChecker(anchor, params));
}
// add user-specified checkers // add user-specified checkers
certPathCheckers.addAll(userCheckers); certPathCheckers.addAll(checkers);
PKIXMasterCertPathValidator masterValidator =
new PKIXMasterCertPathValidator(certPathCheckers);
masterValidator.validate(cpOriginal, certList); PKIXMasterCertPathValidator.validate(params.certPath(),
params.certificates(),
certPathCheckers);
return policyChecker.getPolicyTree(); return new PKIXCertPathValidatorResult(anchor, pc.getPolicyTree(),
bc.getPublicKey());
} }
} }
/* /*
* Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -30,10 +30,8 @@ import sun.security.util.Debug; ...@@ -30,10 +30,8 @@ import sun.security.util.Debug;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.security.cert.CertificateRevokedException;
import java.security.cert.CertPath; import java.security.cert.CertPath;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXCertPathChecker; import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXReason; import java.security.cert.PKIXReason;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
...@@ -49,32 +47,22 @@ import java.security.cert.X509Certificate; ...@@ -49,32 +47,22 @@ import java.security.cert.X509Certificate;
class PKIXMasterCertPathValidator { class PKIXMasterCertPathValidator {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private List<PKIXCertPathChecker> certPathCheckers;
/**
* Initializes the list of PKIXCertPathCheckers whose checks
* will be performed on each certificate in the certpath.
*
* @param certPathCheckers a List of checkers to use
*/
PKIXMasterCertPathValidator(List<PKIXCertPathChecker> certPathCheckers) {
this.certPathCheckers = certPathCheckers;
}
/** /**
* Validates a certification path consisting exclusively of * Validates a certification path consisting exclusively of
* <code>X509Certificate</code>s using the * <code>X509Certificate</code>s using the specified
* <code>PKIXCertPathChecker</code>s specified * <code>PKIXCertPathChecker</code>s. It is assumed that the
* in the constructor. It is assumed that the
* <code>PKIXCertPathChecker</code>s * <code>PKIXCertPathChecker</code>s
* have been initialized with any input parameters they may need. * have been initialized with any input parameters they may need.
* *
* @param cpOriginal the original X509 CertPath passed in by the user * @param cpOriginal the original X509 CertPath passed in by the user
* @param reversedCertList the reversed X509 CertPath (as a List) * @param reversedCertList the reversed X509 CertPath (as a List)
* @exception CertPathValidatorException Exception thrown if cert * @param certPathCheckers the PKIXCertPathCheckers
* path does not validate. * @throws CertPathValidatorException if cert path does not validate
*/ */
void validate(CertPath cpOriginal, List<X509Certificate> reversedCertList) static void validate(CertPath cpOriginal,
List<X509Certificate> reversedCertList,
List<PKIXCertPathChecker> certPathCheckers)
throws CertPathValidatorException throws CertPathValidatorException
{ {
// we actually process reversedCertList, but we keep cpOriginal because // we actually process reversedCertList, but we keep cpOriginal because
...@@ -104,20 +92,18 @@ class PKIXMasterCertPathValidator { ...@@ -104,20 +92,18 @@ class PKIXMasterCertPathValidator {
debug.println("Checking cert" + (i+1) + " ..."); debug.println("Checking cert" + (i+1) + " ...");
X509Certificate currCert = reversedCertList.get(i); X509Certificate currCert = reversedCertList.get(i);
Set<String> unresolvedCritExts = Set<String> unresCritExts = currCert.getCriticalExtensionOIDs();
currCert.getCriticalExtensionOIDs(); if (unresCritExts == null) {
if (unresolvedCritExts == null) { unresCritExts = Collections.<String>emptySet();
unresolvedCritExts = Collections.<String>emptySet();
} }
if (debug != null && !unresolvedCritExts.isEmpty()) { if (debug != null && !unresCritExts.isEmpty()) {
debug.println("Set of critical extensions:"); debug.println("Set of critical extensions:");
for (String oid : unresolvedCritExts) { for (String oid : unresCritExts) {
debug.println(oid); debug.println(oid);
} }
} }
CertPathValidatorException ocspCause = null;
for (int j = 0; j < certPathCheckers.size(); j++) { for (int j = 0; j < certPathCheckers.size(); j++) {
PKIXCertPathChecker currChecker = certPathCheckers.get(j); PKIXCertPathChecker currChecker = certPathCheckers.get(j);
...@@ -130,65 +116,21 @@ class PKIXMasterCertPathValidator { ...@@ -130,65 +116,21 @@ class PKIXMasterCertPathValidator {
currChecker.init(false); currChecker.init(false);
try { try {
currChecker.check(currCert, unresolvedCritExts); currChecker.check(currCert, unresCritExts);
// OCSP has validated the cert so skip the CRL check
if (isRevocationCheck(currChecker, j, certPathCheckers)) {
if (debug != null) {
debug.println("-checker" + (j + 1) +
" validation succeeded");
}
j++;
continue; // skip
}
} catch (CertPathValidatorException cpve) {
// Throw the saved OCSP exception unless the CRL
// checker has determined that the cert is revoked
if (ocspCause != null &&
currChecker instanceof CrlRevocationChecker) {
if (cpve.getReason() == BasicReason.REVOKED) {
throw cpve;
} else {
throw ocspCause;
}
}
/*
* Handle failover from OCSP to CRLs
*/
CertPathValidatorException currentCause =
new CertPathValidatorException(cpve.getMessage(),
cpve.getCause(), cpOriginal, cpSize - (i + 1),
cpve.getReason());
// Check if OCSP has confirmed that the cert was revoked
if (cpve.getReason() == BasicReason.REVOKED) {
throw currentCause;
}
// Check if it is appropriate to failover
if (! isRevocationCheck(currChecker, j, certPathCheckers)) {
// no failover
throw currentCause;
}
// Save the current exception
// (in case the CRL check also fails)
ocspCause = currentCause;
// Otherwise, failover to CRLs
if (debug != null) { if (debug != null) {
debug.println(cpve.getMessage()); debug.println("-checker" + (j + 1) +
debug.println( " validation succeeded");
"preparing to failover (from OCSP to CRLs)");
} }
}
if (debug != null) } catch (CertPathValidatorException cpve) {
debug.println("-checker" + (j+1) + " validation succeeded"); throw new CertPathValidatorException(cpve.getMessage(),
cpve.getCause(), cpOriginal, cpSize - (i + 1),
cpve.getReason());
}
} }
if (debug != null) if (!unresCritExts.isEmpty()) {
debug.println("checking for unresolvedCritExts");
if (!unresolvedCritExts.isEmpty()) {
throw new CertPathValidatorException("unrecognized " + throw new CertPathValidatorException("unrecognized " +
"critical extension(s)", null, cpOriginal, cpSize-(i+1), "critical extension(s)", null, cpOriginal, cpSize-(i+1),
PKIXReason.UNRECOGNIZED_CRIT_EXT); PKIXReason.UNRECOGNIZED_CRIT_EXT);
...@@ -200,26 +142,9 @@ class PKIXMasterCertPathValidator { ...@@ -200,26 +142,9 @@ class PKIXMasterCertPathValidator {
if (debug != null) { if (debug != null) {
debug.println("Cert path validation succeeded. (PKIX validation " debug.println("Cert path validation succeeded. (PKIX validation "
+ "algorithm)"); + "algorithm)");
debug.println("-------------------------------------------------" debug.println("-------------------------------------------------"
+ "-------------"); + "-------------");
}
}
/*
* Examines the list of PKIX cert path checkers to determine whether
* both the current checker and the next checker are revocation checkers.
* OCSPChecker and CrlRevocationChecker are both revocation checkers.
*/
private static boolean isRevocationCheck(PKIXCertPathChecker checker,
int index, List<PKIXCertPathChecker> checkers) {
if (checker instanceof OCSPChecker && index + 1 < checkers.size()) {
PKIXCertPathChecker nextChecker = checkers.get(index + 1);
if (nextChecker instanceof CrlRevocationChecker) {
return true;
}
} }
return false;
} }
} }
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.util.*;
import java.io.IOException; import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException; import java.security.cert.CertPathValidatorException;
...@@ -36,13 +35,14 @@ import java.security.cert.PKIXReason; ...@@ -36,13 +35,14 @@ import java.security.cert.PKIXReason;
import java.security.cert.PolicyNode; import java.security.cert.PolicyNode;
import java.security.cert.PolicyQualifierInfo; import java.security.cert.PolicyQualifierInfo;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.*;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.CertificatePoliciesExtension; import sun.security.x509.CertificatePoliciesExtension;
import sun.security.x509.PolicyConstraintsExtension; import sun.security.x509.PolicyConstraintsExtension;
import sun.security.x509.PolicyMappingsExtension; import sun.security.x509.PolicyMappingsExtension;
import sun.security.x509.CertificatePolicyMap; import sun.security.x509.CertificatePolicyMap;
import sun.security.x509.PKIXExtensions; import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.PolicyInformation; import sun.security.x509.PolicyInformation;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
import sun.security.x509.InhibitAnyPolicyExtension; import sun.security.x509.InhibitAnyPolicyExtension;
...@@ -88,7 +88,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -88,7 +88,7 @@ class PolicyChecker extends PKIXCertPathChecker {
PolicyChecker(Set<String> initialPolicies, int certPathLen, PolicyChecker(Set<String> initialPolicies, int certPathLen,
boolean expPolicyRequired, boolean polMappingInhibited, boolean expPolicyRequired, boolean polMappingInhibited,
boolean anyPolicyInhibited, boolean rejectPolicyQualifiers, boolean anyPolicyInhibited, boolean rejectPolicyQualifiers,
PolicyNodeImpl rootNode) throws CertPathValidatorException PolicyNodeImpl rootNode)
{ {
if (initialPolicies.isEmpty()) { if (initialPolicies.isEmpty()) {
// if no initialPolicies are specified by user, set // if no initialPolicies are specified by user, set
...@@ -104,18 +104,18 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -104,18 +104,18 @@ class PolicyChecker extends PKIXCertPathChecker {
this.anyPolicyInhibited = anyPolicyInhibited; this.anyPolicyInhibited = anyPolicyInhibited;
this.rejectPolicyQualifiers = rejectPolicyQualifiers; this.rejectPolicyQualifiers = rejectPolicyQualifiers;
this.rootNode = rootNode; this.rootNode = rootNode;
init(false);
} }
/** /**
* Initializes the internal state of the checker from parameters * Initializes the internal state of the checker from parameters
* specified in the constructor * specified in the constructor
* *
* @param forward a boolean indicating whether this checker should * @param forward a boolean indicating whether this checker should be
* be initialized capable of building in the forward direction * initialized capable of building in the forward direction
* @exception CertPathValidatorException Exception thrown if user * @throws CertPathValidatorException if user wants to enable forward
* wants to enable forward checking and forward checking is not supported. * checking and forward checking is not supported.
*/ */
@Override
public void init(boolean forward) throws CertPathValidatorException { public void init(boolean forward) throws CertPathValidatorException {
if (forward) { if (forward) {
throw new CertPathValidatorException throw new CertPathValidatorException
...@@ -136,6 +136,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -136,6 +136,7 @@ class PolicyChecker extends PKIXCertPathChecker {
* *
* @return true if forward checking is supported, false otherwise * @return true if forward checking is supported, false otherwise
*/ */
@Override
public boolean isForwardCheckingSupported() { public boolean isForwardCheckingSupported() {
return false; return false;
} }
...@@ -150,13 +151,14 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -150,13 +151,14 @@ class PolicyChecker extends PKIXCertPathChecker {
* @return the Set of extensions supported by this PKIXCertPathChecker, * @return the Set of extensions supported by this PKIXCertPathChecker,
* or null if no extensions are supported * or null if no extensions are supported
*/ */
@Override
public Set<String> getSupportedExtensions() { public Set<String> getSupportedExtensions() {
if (supportedExts == null) { if (supportedExts == null) {
supportedExts = new HashSet<String>(); supportedExts = new HashSet<String>(4);
supportedExts.add(PKIXExtensions.CertificatePolicies_Id.toString()); supportedExts.add(CertificatePolicies_Id.toString());
supportedExts.add(PKIXExtensions.PolicyMappings_Id.toString()); supportedExts.add(PolicyMappings_Id.toString());
supportedExts.add(PKIXExtensions.PolicyConstraints_Id.toString()); supportedExts.add(PolicyConstraints_Id.toString());
supportedExts.add(PKIXExtensions.InhibitAnyPolicy_Id.toString()); supportedExts.add(InhibitAnyPolicy_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts); supportedExts = Collections.unmodifiableSet(supportedExts);
} }
return supportedExts; return supportedExts;
...@@ -168,9 +170,9 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -168,9 +170,9 @@ class PolicyChecker extends PKIXCertPathChecker {
* *
* @param cert the Certificate to be processed * @param cert the Certificate to be processed
* @param unresCritExts the unresolved critical extensions * @param unresCritExts the unresolved critical extensions
* @exception CertPathValidatorException Exception thrown if * @throws CertPathValidatorException if the certificate does not verify
* the certificate does not verify.
*/ */
@Override
public void check(Certificate cert, Collection<String> unresCritExts) public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException throws CertPathValidatorException
{ {
...@@ -178,10 +180,10 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -178,10 +180,10 @@ class PolicyChecker extends PKIXCertPathChecker {
checkPolicy((X509Certificate) cert); checkPolicy((X509Certificate) cert);
if (unresCritExts != null && !unresCritExts.isEmpty()) { if (unresCritExts != null && !unresCritExts.isEmpty()) {
unresCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString()); unresCritExts.remove(CertificatePolicies_Id.toString());
unresCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString()); unresCritExts.remove(PolicyMappings_Id.toString());
unresCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString()); unresCritExts.remove(PolicyConstraints_Id.toString());
unresCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString()); unresCritExts.remove(InhibitAnyPolicy_Id.toString());
} }
} }
...@@ -290,7 +292,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -290,7 +292,7 @@ class PolicyChecker extends PKIXCertPathChecker {
if (require == 0) if (require == 0)
explicitPolicy = require; explicitPolicy = require;
} }
} catch (Exception e) { } catch (IOException e) {
if (debug != null) { if (debug != null) {
debug.println("PolicyChecker.mergeExplicitPolicy " debug.println("PolicyChecker.mergeExplicitPolicy "
+ "unexpected exception"); + "unexpected exception");
...@@ -339,7 +341,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -339,7 +341,7 @@ class PolicyChecker extends PKIXCertPathChecker {
policyMapping = inhibit; policyMapping = inhibit;
} }
} }
} catch (Exception e) { } catch (IOException e) {
if (debug != null) { if (debug != null) {
debug.println("PolicyChecker.mergePolicyMapping " debug.println("PolicyChecker.mergePolicyMapping "
+ "unexpected exception"); + "unexpected exception");
...@@ -372,7 +374,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -372,7 +374,7 @@ class PolicyChecker extends PKIXCertPathChecker {
try { try {
InhibitAnyPolicyExtension inhAnyPolExt = (InhibitAnyPolicyExtension) InhibitAnyPolicyExtension inhAnyPolExt = (InhibitAnyPolicyExtension)
currCert.getExtension(PKIXExtensions.InhibitAnyPolicy_Id); currCert.getExtension(InhibitAnyPolicy_Id);
if (inhAnyPolExt == null) if (inhAnyPolExt == null)
return inhibitAnyPolicy; return inhibitAnyPolicy;
...@@ -387,7 +389,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -387,7 +389,7 @@ class PolicyChecker extends PKIXCertPathChecker {
inhibitAnyPolicy = skipCerts; inhibitAnyPolicy = skipCerts;
} }
} }
} catch (Exception e) { } catch (IOException e) {
if (debug != null) { if (debug != null) {
debug.println("PolicyChecker.mergeInhibitAnyPolicy " debug.println("PolicyChecker.mergeInhibitAnyPolicy "
+ "unexpected exception"); + "unexpected exception");
...@@ -429,7 +431,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -429,7 +431,7 @@ class PolicyChecker extends PKIXCertPathChecker {
boolean policiesCritical = false; boolean policiesCritical = false;
List<PolicyInformation> policyInfo; List<PolicyInformation> policyInfo;
PolicyNodeImpl rootNode = null; PolicyNodeImpl rootNode = null;
Set<PolicyQualifierInfo> anyQuals = new HashSet<PolicyQualifierInfo>(); Set<PolicyQualifierInfo> anyQuals = new HashSet<>();
if (origRootNode == null) if (origRootNode == null)
rootNode = null; rootNode = null;
...@@ -600,7 +602,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -600,7 +602,7 @@ class PolicyChecker extends PKIXCertPathChecker {
PolicyNodeImpl parentNode = (PolicyNodeImpl)anyNode.getParent(); PolicyNodeImpl parentNode = (PolicyNodeImpl)anyNode.getParent();
parentNode.deleteChild(anyNode); parentNode.deleteChild(anyNode);
// see if there are any initialPolicies not represented by leaf nodes // see if there are any initialPolicies not represented by leaf nodes
Set<String> initial = new HashSet<String>(initPolicies); Set<String> initial = new HashSet<>(initPolicies);
for (PolicyNodeImpl node : rootNode.getPolicyNodes(certIndex)) { for (PolicyNodeImpl node : rootNode.getPolicyNodes(certIndex)) {
initial.remove(node.getValidPolicy()); initial.remove(node.getValidPolicy());
} }
...@@ -697,7 +699,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -697,7 +699,7 @@ class PolicyChecker extends PKIXCertPathChecker {
} }
} }
Set<String> expPols = new HashSet<String>(); Set<String> expPols = new HashSet<>();
expPols.add(curParExpPol); expPols.add(curParExpPol);
curNode = new PolicyNodeImpl curNode = new PolicyNodeImpl
...@@ -762,8 +764,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -762,8 +764,7 @@ class PolicyChecker extends PKIXCertPathChecker {
} }
boolean childDeleted = false; boolean childDeleted = false;
for (int j = 0; j < maps.size(); j++) { for (CertificatePolicyMap polMap : maps) {
CertificatePolicyMap polMap = maps.get(j);
String issuerDomain String issuerDomain
= polMap.getIssuerIdentifier().getIdentifier().toString(); = polMap.getIssuerIdentifier().getIdentifier().toString();
String subjectDomain String subjectDomain
...@@ -816,7 +817,7 @@ class PolicyChecker extends PKIXCertPathChecker { ...@@ -816,7 +817,7 @@ class PolicyChecker extends PKIXCertPathChecker {
PolicyNodeImpl curAnyNodeParent = PolicyNodeImpl curAnyNodeParent =
(PolicyNodeImpl) curAnyNode.getParent(); (PolicyNodeImpl) curAnyNode.getParent();
Set<String> expPols = new HashSet<String>(); Set<String> expPols = new HashSet<>();
expPols.add(subjectDomain); expPols.add(subjectDomain);
PolicyNodeImpl curNode = new PolicyNodeImpl PolicyNodeImpl curNode = new PolicyNodeImpl
......
/* /*
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -134,30 +134,37 @@ final class PolicyNodeImpl implements PolicyNode { ...@@ -134,30 +134,37 @@ final class PolicyNodeImpl implements PolicyNode {
node.mCriticalityIndicator, node.mExpectedPolicySet, false); node.mCriticalityIndicator, node.mExpectedPolicySet, false);
} }
@Override
public PolicyNode getParent() { public PolicyNode getParent() {
return mParent; return mParent;
} }
@Override
public Iterator<PolicyNodeImpl> getChildren() { public Iterator<PolicyNodeImpl> getChildren() {
return Collections.unmodifiableSet(mChildren).iterator(); return Collections.unmodifiableSet(mChildren).iterator();
} }
@Override
public int getDepth() { public int getDepth() {
return mDepth; return mDepth;
} }
@Override
public String getValidPolicy() { public String getValidPolicy() {
return mValidPolicy; return mValidPolicy;
} }
@Override
public Set<PolicyQualifierInfo> getPolicyQualifiers() { public Set<PolicyQualifierInfo> getPolicyQualifiers() {
return Collections.unmodifiableSet(mQualifierSet); return Collections.unmodifiableSet(mQualifierSet);
} }
@Override
public Set<String> getExpectedPolicies() { public Set<String> getExpectedPolicies() {
return Collections.unmodifiableSet(mExpectedPolicySet); return Collections.unmodifiableSet(mExpectedPolicySet);
} }
@Override
public boolean isCritical() { public boolean isCritical() {
return mCriticalityIndicator; return mCriticalityIndicator;
} }
...@@ -169,12 +176,12 @@ final class PolicyNodeImpl implements PolicyNode { ...@@ -169,12 +176,12 @@ final class PolicyNodeImpl implements PolicyNode {
* *
* @return a String describing the contents of the Policy Node * @return a String describing the contents of the Policy Node
*/ */
@Override
public String toString() { public String toString() {
StringBuffer buffer = new StringBuffer(this.asString()); StringBuilder buffer = new StringBuilder(this.asString());
Iterator<PolicyNodeImpl> it = getChildren(); for (PolicyNodeImpl node : mChildren) {
while (it.hasNext()) { buffer.append(node);
buffer.append(it.next());
} }
return buffer.toString(); return buffer.toString();
} }
...@@ -293,7 +300,7 @@ final class PolicyNodeImpl implements PolicyNode { ...@@ -293,7 +300,7 @@ final class PolicyNodeImpl implements PolicyNode {
* @return a <code>Set</code> of all nodes at the specified depth * @return a <code>Set</code> of all nodes at the specified depth
*/ */
Set<PolicyNodeImpl> getPolicyNodes(int depth) { Set<PolicyNodeImpl> getPolicyNodes(int depth) {
Set<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>(); Set<PolicyNodeImpl> set = new HashSet<>();
getPolicyNodes(depth, set); getPolicyNodes(depth, set);
return set; return set;
} }
...@@ -337,7 +344,7 @@ final class PolicyNodeImpl implements PolicyNode { ...@@ -337,7 +344,7 @@ final class PolicyNodeImpl implements PolicyNode {
private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth, private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth,
String expectedOID, boolean matchAny) { String expectedOID, boolean matchAny) {
HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>(); HashSet<PolicyNodeImpl> set = new HashSet<>();
if (mDepth < depth) { if (mDepth < depth) {
for (PolicyNodeImpl node : mChildren) { for (PolicyNodeImpl node : mChildren) {
...@@ -367,7 +374,7 @@ final class PolicyNodeImpl implements PolicyNode { ...@@ -367,7 +374,7 @@ final class PolicyNodeImpl implements PolicyNode {
* @return a Set of matched <code>PolicyNode</code>s * @return a Set of matched <code>PolicyNode</code>s
*/ */
Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) { Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) {
HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>(); HashSet<PolicyNodeImpl> set = new HashSet<>();
if (mDepth < depth) { if (mDepth < depth) {
for (PolicyNodeImpl node : mChildren) { for (PolicyNodeImpl node : mChildren) {
...@@ -396,7 +403,7 @@ final class PolicyNodeImpl implements PolicyNode { ...@@ -396,7 +403,7 @@ final class PolicyNodeImpl implements PolicyNode {
if (mParent == null) { if (mParent == null) {
return "anyPolicy ROOT\n"; return "anyPolicy ROOT\n";
} else { } else {
StringBuffer sb = new StringBuffer(); StringBuilder sb = new StringBuilder();
for (int i = 0, n = getDepth(); i < n; i++) { for (int i = 0, n = getDepth(); i < n; i++) {
sb.append(" "); sb.append(" ");
} }
......
/* /*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -51,9 +51,10 @@ import java.util.Set; ...@@ -51,9 +51,10 @@ import java.util.Set;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.Extension; import sun.security.x509.Extension;
import sun.security.x509.PKIXExtensions; import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.X500Name; import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl; import sun.security.x509.X509CertImpl;
import sun.security.x509.PolicyMappingsExtension; import sun.security.x509.PolicyMappingsExtension;
...@@ -72,28 +73,24 @@ class ReverseBuilder extends Builder { ...@@ -72,28 +73,24 @@ class ReverseBuilder extends Builder {
private Debug debug = Debug.getInstance("certpath"); private Debug debug = Debug.getInstance("certpath");
Set<String> initPolicies; private final Set<String> initPolicies;
/** /**
* Initialize the builder with the input parameters. * Initialize the builder with the input parameters.
* *
* @param params the parameter set used to build a certification path * @param params the parameter set used to build a certification path
*/ */
ReverseBuilder(PKIXBuilderParameters buildParams, ReverseBuilder(BuilderParams buildParams) {
X500Principal targetSubjectDN) { super(buildParams);
super(buildParams, targetSubjectDN); Set<String> initialPolicies = buildParams.initialPolicies();
Set<String> initialPolicies = buildParams.getInitialPolicies();
initPolicies = new HashSet<String>(); initPolicies = new HashSet<String>();
if (initialPolicies.isEmpty()) { if (initialPolicies.isEmpty()) {
// if no initialPolicies are specified by user, set // if no initialPolicies are specified by user, set
// initPolicies to be anyPolicy by default // initPolicies to be anyPolicy by default
initPolicies.add(PolicyChecker.ANY_POLICY); initPolicies.add(PolicyChecker.ANY_POLICY);
} else { } else {
for (String policy : initialPolicies) { initPolicies.addAll(initialPolicies);
initPolicies.add(policy);
}
} }
} }
...@@ -106,6 +103,7 @@ class ReverseBuilder extends Builder { ...@@ -106,6 +103,7 @@ class ReverseBuilder extends Builder {
* Must be an instance of <code>ReverseState</code> * Must be an instance of <code>ReverseState</code>
* @param certStores list of CertStores * @param certStores list of CertStores
*/ */
@Override
Collection<X509Certificate> getMatchingCerts Collection<X509Certificate> getMatchingCerts
(State currState, List<CertStore> certStores) (State currState, List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException throws CertStoreException, CertificateException, IOException
...@@ -138,56 +136,56 @@ class ReverseBuilder extends Builder { ...@@ -138,56 +136,56 @@ class ReverseBuilder extends Builder {
(ReverseState currentState, List<CertStore> certStores) (ReverseState currentState, List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException { throws CertStoreException, CertificateException, IOException {
/* /*
* Compose a CertSelector to filter out * Compose a CertSelector to filter out
* certs which do not satisfy requirements. * certs which do not satisfy requirements.
* *
* First, retrieve clone of current target cert constraints, * First, retrieve clone of current target cert constraints, and
* and then add more selection criteria based on current validation state. * then add more selection criteria based on current validation state.
*/ */
X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone(); X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
/* /*
* Match on issuer (subject of previous cert) * Match on issuer (subject of previous cert)
*/ */
sel.setIssuer(currentState.subjectDN); sel.setIssuer(currentState.subjectDN);
/* /*
* Match on certificate validity date. * Match on certificate validity date.
*/ */
sel.setCertificateValid(date); sel.setCertificateValid(buildParams.date());
/* /*
* Policy processing optimizations * Policy processing optimizations
*/ */
if (currentState.explicitPolicy == 0) if (currentState.explicitPolicy == 0)
sel.setPolicy(getMatchingPolicies()); sel.setPolicy(getMatchingPolicies());
/* /*
* If previous cert has a subject key identifier extension, * If previous cert has a subject key identifier extension,
* use it to match on authority key identifier extension. * use it to match on authority key identifier extension.
*/ */
/*if (currentState.subjKeyId != null) { /*if (currentState.subjKeyId != null) {
AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension( AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
(KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID), (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
null, null); null, null);
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue()); sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
}*/ }*/
/* /*
* Require EE certs * Require EE certs
*/ */
sel.setBasicConstraints(-2); sel.setBasicConstraints(-2);
/* Retrieve matching certs from CertStores */ /* Retrieve matching certs from CertStores */
HashSet<X509Certificate> eeCerts = new HashSet<X509Certificate>(); HashSet<X509Certificate> eeCerts = new HashSet<>();
addMatchingCerts(sel, certStores, eeCerts, true); addMatchingCerts(sel, certStores, eeCerts, true);
if (debug != null) { if (debug != null) {
debug.println("ReverseBuilder.getMatchingEECerts got " + eeCerts.size() debug.println("ReverseBuilder.getMatchingEECerts got "
+ " certs."); + eeCerts.size() + " certs.");
} }
return eeCerts; return eeCerts;
} }
/* /*
...@@ -198,63 +196,71 @@ class ReverseBuilder extends Builder { ...@@ -198,63 +196,71 @@ class ReverseBuilder extends Builder {
(ReverseState currentState, List<CertStore> certStores) (ReverseState currentState, List<CertStore> certStores)
throws CertificateException, CertStoreException, IOException { throws CertificateException, CertStoreException, IOException {
/* /*
* Compose a CertSelector to filter out * Compose a CertSelector to filter out
* certs which do not satisfy requirements. * certs which do not satisfy requirements.
*/ */
X509CertSelector sel = new X509CertSelector(); X509CertSelector sel = new X509CertSelector();
/* /*
* Match on issuer (subject of previous cert) * Match on issuer (subject of previous cert)
*/ */
sel.setIssuer(currentState.subjectDN); sel.setIssuer(currentState.subjectDN);
/* /*
* Match on certificate validity date. * Match on certificate validity date.
*/ */
sel.setCertificateValid(date); sel.setCertificateValid(buildParams.date());
/* /*
* Match on target subject name (checks that current cert's * Match on target subject name (checks that current cert's
* name constraints permit it to certify target). * name constraints permit it to certify target).
* (4 is the integer type for DIRECTORY name). * (4 is the integer type for DIRECTORY name).
*/ */
sel.addPathToName(4, targetCertConstraints.getSubjectAsBytes()); byte[] subject = targetCertConstraints.getSubjectAsBytes();
if (subject != null) {
/* sel.addPathToName(4, subject);
* Policy processing optimizations } else {
*/ X509Certificate cert = targetCertConstraints.getCertificate();
if (currentState.explicitPolicy == 0) if (cert != null) {
sel.setPolicy(getMatchingPolicies()); sel.addPathToName(4,
cert.getSubjectX500Principal().getEncoded());
/* }
* If previous cert has a subject key identifier extension, }
* use it to match on authority key identifier extension.
*/ /*
/*if (currentState.subjKeyId != null) { * Policy processing optimizations
AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension( */
if (currentState.explicitPolicy == 0)
sel.setPolicy(getMatchingPolicies());
/*
* If previous cert has a subject key identifier extension,
* use it to match on authority key identifier extension.
*/
/*if (currentState.subjKeyId != null) {
AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
(KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID), (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
null, null); null, null);
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue()); sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
}*/ }*/
/* /*
* Require CA certs * Require CA certs
*/ */
sel.setBasicConstraints(0); sel.setBasicConstraints(0);
/* Retrieve matching certs from CertStores */ /* Retrieve matching certs from CertStores */
ArrayList<X509Certificate> reverseCerts = ArrayList<X509Certificate> reverseCerts = new ArrayList<>();
new ArrayList<X509Certificate>(); addMatchingCerts(sel, certStores, reverseCerts, true);
addMatchingCerts(sel, certStores, reverseCerts, true);
/* Sort remaining certs using name constraints */ /* Sort remaining certs using name constraints */
Collections.sort(reverseCerts, new PKIXCertComparator()); Collections.sort(reverseCerts, new PKIXCertComparator());
if (debug != null) if (debug != null)
debug.println("ReverseBuilder.getMatchingCACerts got " + debug.println("ReverseBuilder.getMatchingCACerts got " +
reverseCerts.size() + " certs."); reverseCerts.size() + " certs.");
return reverseCerts; return reverseCerts;
} }
/* /*
...@@ -269,23 +275,25 @@ class ReverseBuilder extends Builder { ...@@ -269,23 +275,25 @@ class ReverseBuilder extends Builder {
private Debug debug = Debug.getInstance("certpath"); private Debug debug = Debug.getInstance("certpath");
@Override
public int compare(X509Certificate cert1, X509Certificate cert2) { public int compare(X509Certificate cert1, X509Certificate cert2) {
/* /*
* if either cert certifies the target, always * if either cert certifies the target, always
* put at head of list. * put at head of list.
*/ */
if (cert1.getSubjectX500Principal().equals(targetSubjectDN)) { X500Principal targetSubject = buildParams.targetSubject();
if (cert1.getSubjectX500Principal().equals(targetSubject)) {
return -1; return -1;
} }
if (cert2.getSubjectX500Principal().equals(targetSubjectDN)) { if (cert2.getSubjectX500Principal().equals(targetSubject)) {
return 1; return 1;
} }
int targetDist1; int targetDist1;
int targetDist2; int targetDist2;
try { try {
X500Name targetSubjectName = X500Name.asX500Name(targetSubjectDN); X500Name targetSubjectName = X500Name.asX500Name(targetSubject);
targetDist1 = Builder.targetDistance( targetDist1 = Builder.targetDistance(
null, cert1, targetSubjectName); null, cert1, targetSubjectName);
targetDist2 = Builder.targetDistance( targetDist2 = Builder.targetDistance(
...@@ -330,6 +338,7 @@ class ReverseBuilder extends Builder { ...@@ -330,6 +338,7 @@ class ReverseBuilder extends Builder {
* @param currentState the current state against which the cert is verified * @param currentState the current state against which the cert is verified
* @param certPathList the certPathList generated thus far * @param certPathList the certPathList generated thus far
*/ */
@Override
void verifyCert(X509Certificate cert, State currState, void verifyCert(X509Certificate cert, State currState,
List<X509Certificate> certPathList) List<X509Certificate> certPathList)
throws GeneralSecurityException throws GeneralSecurityException
...@@ -358,8 +367,7 @@ class ReverseBuilder extends Builder { ...@@ -358,8 +367,7 @@ class ReverseBuilder extends Builder {
* of the same certificate, we reverse the certpathlist first * of the same certificate, we reverse the certpathlist first
*/ */
if ((certPathList != null) && (!certPathList.isEmpty())) { if ((certPathList != null) && (!certPathList.isEmpty())) {
List<X509Certificate> reverseCertList = List<X509Certificate> reverseCertList = new ArrayList<>();
new ArrayList<X509Certificate>();
for (X509Certificate c : certPathList) { for (X509Certificate c : certPathList) {
reverseCertList.add(0, c); reverseCertList.add(0, c);
} }
...@@ -374,8 +382,8 @@ class ReverseBuilder extends Builder { ...@@ -374,8 +382,8 @@ class ReverseBuilder extends Builder {
} }
if (debug != null) if (debug != null)
debug.println("policyMappingFound = " + policyMappingFound); debug.println("policyMappingFound = " + policyMappingFound);
if (cert.equals(cpListCert)){ if (cert.equals(cpListCert)) {
if ((buildParams.isPolicyMappingInhibited()) || if ((buildParams.policyMappingInhibited()) ||
(!policyMappingFound)){ (!policyMappingFound)){
if (debug != null) if (debug != null)
debug.println("loop detected!!"); debug.println("loop detected!!");
...@@ -386,7 +394,7 @@ class ReverseBuilder extends Builder { ...@@ -386,7 +394,7 @@ class ReverseBuilder extends Builder {
} }
/* check if target cert */ /* check if target cert */
boolean finalCert = cert.getSubjectX500Principal().equals(targetSubjectDN); boolean finalCert = cert.getSubjectX500Principal().equals(buildParams.targetSubject());
/* check if CA cert */ /* check if CA cert */
boolean caCert = (cert.getBasicConstraints() != -1 ? true : false); boolean caCert = (cert.getBasicConstraints() != -1 ? true : false);
...@@ -427,23 +435,20 @@ class ReverseBuilder extends Builder { ...@@ -427,23 +435,20 @@ class ReverseBuilder extends Builder {
/* /*
* Check revocation. * Check revocation.
*/ */
if (buildParams.isRevocationEnabled()) { if (buildParams.revocationEnabled() && currentState.revChecker != null) {
currentState.revChecker.check(cert, Collections.<String>emptySet());
currentState.crlChecker.check(cert,
currentState.pubKey,
currentState.crlSign);
} }
/* Check name constraints if this is not a self-issued cert */ /* Check name constraints if this is not a self-issued cert */
if (finalCert || !X509CertImpl.isSelfIssued(cert)){ if (finalCert || !X509CertImpl.isSelfIssued(cert)){
if (currentState.nc != null){ if (currentState.nc != null) {
try { try {
if (!currentState.nc.verify(cert)){ if (!currentState.nc.verify(cert)){
throw new CertPathValidatorException throw new CertPathValidatorException
("name constraints check failed", null, null, -1, ("name constraints check failed", null, null, -1,
PKIXReason.INVALID_NAME); PKIXReason.INVALID_NAME);
} }
} catch (IOException ioe){ } catch (IOException ioe) {
throw new CertPathValidatorException(ioe); throw new CertPathValidatorException(ioe);
} }
} }
...@@ -457,7 +462,7 @@ class ReverseBuilder extends Builder { ...@@ -457,7 +462,7 @@ class ReverseBuilder extends Builder {
(currentState.certIndex, initPolicies, (currentState.certIndex, initPolicies,
currentState.explicitPolicy, currentState.policyMapping, currentState.explicitPolicy, currentState.policyMapping,
currentState.inhibitAnyPolicy, currentState.inhibitAnyPolicy,
buildParams.getPolicyQualifiersRejected(), currentState.rootNode, buildParams.policyQualifiersRejected(), currentState.rootNode,
certImpl, finalCert); certImpl, finalCert);
/* /*
...@@ -482,15 +487,15 @@ class ReverseBuilder extends Builder { ...@@ -482,15 +487,15 @@ class ReverseBuilder extends Builder {
* already checked. If there are any left, throw an exception! * already checked. If there are any left, throw an exception!
*/ */
if (!unresolvedCritExts.isEmpty()) { if (!unresolvedCritExts.isEmpty()) {
unresolvedCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString()); unresolvedCritExts.remove(BasicConstraints_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.NameConstraints_Id.toString()); unresolvedCritExts.remove(NameConstraints_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString()); unresolvedCritExts.remove(CertificatePolicies_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString()); unresolvedCritExts.remove(PolicyMappings_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString()); unresolvedCritExts.remove(PolicyConstraints_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString()); unresolvedCritExts.remove(InhibitAnyPolicy_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.SubjectAlternativeName_Id.toString()); unresolvedCritExts.remove(SubjectAlternativeName_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.KeyUsage_Id.toString()); unresolvedCritExts.remove(KeyUsage_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString()); unresolvedCritExts.remove(ExtendedKeyUsage_Id.toString());
if (!unresolvedCritExts.isEmpty()) if (!unresolvedCritExts.isEmpty())
throw new CertPathValidatorException throw new CertPathValidatorException
...@@ -501,8 +506,8 @@ class ReverseBuilder extends Builder { ...@@ -501,8 +506,8 @@ class ReverseBuilder extends Builder {
/* /*
* Check signature. * Check signature.
*/ */
if (buildParams.getSigProvider() != null) { if (buildParams.sigProvider() != null) {
cert.verify(currentState.pubKey, buildParams.getSigProvider()); cert.verify(currentState.pubKey, buildParams.sigProvider());
} else { } else {
cert.verify(currentState.pubKey); cert.verify(currentState.pubKey);
} }
...@@ -515,8 +520,9 @@ class ReverseBuilder extends Builder { ...@@ -515,8 +520,9 @@ class ReverseBuilder extends Builder {
* @param cert the certificate to test * @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path. * @return a boolean value indicating whether the cert completes the path.
*/ */
@Override
boolean isPathCompleted(X509Certificate cert) { boolean isPathCompleted(X509Certificate cert) {
return cert.getSubjectX500Principal().equals(targetSubjectDN); return cert.getSubjectX500Principal().equals(buildParams.targetSubject());
} }
/** Adds the certificate to the certPathList /** Adds the certificate to the certPathList
...@@ -524,6 +530,7 @@ class ReverseBuilder extends Builder { ...@@ -524,6 +530,7 @@ class ReverseBuilder extends Builder {
* @param cert the certificate to be added * @param cert the certificate to be added
* @param certPathList the certification path list * @param certPathList the certification path list
*/ */
@Override
void addCertToPath(X509Certificate cert, void addCertToPath(X509Certificate cert,
LinkedList<X509Certificate> certPathList) { LinkedList<X509Certificate> certPathList) {
certPathList.addLast(cert); certPathList.addLast(cert);
...@@ -533,6 +540,7 @@ class ReverseBuilder extends Builder { ...@@ -533,6 +540,7 @@ class ReverseBuilder extends Builder {
* *
* @param certPathList the certification path list * @param certPathList the certification path list
*/ */
@Override
void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) { void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
certPathList.removeLast(); certPathList.removeLast();
} }
......
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -40,6 +40,7 @@ import java.util.ListIterator; ...@@ -40,6 +40,7 @@ import java.util.ListIterator;
import java.util.Set; import java.util.Set;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.NameConstraintsExtension; import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.SubjectKeyIdentifierExtension; import sun.security.x509.SubjectKeyIdentifierExtension;
...@@ -94,7 +95,7 @@ class ReverseState implements State { ...@@ -94,7 +95,7 @@ class ReverseState implements State {
private boolean init = true; private boolean init = true;
/* the checker used for revocation status */ /* the checker used for revocation status */
public CrlRevocationChecker crlChecker; RevocationChecker revChecker;
/* the algorithm checker */ /* the algorithm checker */
AlgorithmChecker algorithmChecker; AlgorithmChecker algorithmChecker;
...@@ -105,7 +106,7 @@ class ReverseState implements State { ...@@ -105,7 +106,7 @@ class ReverseState implements State {
/* Flag indicating if current cert can vouch for the CRL for /* Flag indicating if current cert can vouch for the CRL for
* the next cert * the next cert
*/ */
public boolean crlSign = true; boolean crlSign = true;
/** /**
* Returns a boolean flag indicating if the state is initial * Returns a boolean flag indicating if the state is initial
...@@ -113,6 +114,7 @@ class ReverseState implements State { ...@@ -113,6 +114,7 @@ class ReverseState implements State {
* *
* @return boolean flag indicating if the state is initial (just starting) * @return boolean flag indicating if the state is initial (just starting)
*/ */
@Override
public boolean isInitial() { public boolean isInitial() {
return init; return init;
} }
...@@ -120,44 +122,32 @@ class ReverseState implements State { ...@@ -120,44 +122,32 @@ class ReverseState implements State {
/** /**
* Display state for debugging purposes * Display state for debugging purposes
*/ */
@Override
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuilder sb = new StringBuilder();
try { sb.append("State [");
sb.append("State ["); sb.append("\n subjectDN of last cert: ").append(subjectDN);
sb.append("\n subjectDN of last cert: " + subjectDN); sb.append("\n subjectKeyIdentifier: ").append
sb.append("\n subjectKeyIdentifier: " + String.valueOf(subjKeyId)); (String.valueOf(subjKeyId));
sb.append("\n nameConstraints: " + String.valueOf(nc)); sb.append("\n nameConstraints: ").append(String.valueOf(nc));
sb.append("\n certIndex: " + certIndex); sb.append("\n certIndex: ").append(certIndex);
sb.append("\n explicitPolicy: " + explicitPolicy); sb.append("\n explicitPolicy: ").append(explicitPolicy);
sb.append("\n policyMapping: " + policyMapping); sb.append("\n policyMapping: ").append(policyMapping);
sb.append("\n inhibitAnyPolicy: " + inhibitAnyPolicy); sb.append("\n inhibitAnyPolicy: ").append(inhibitAnyPolicy);
sb.append("\n rootNode: " + rootNode); sb.append("\n rootNode: ").append(rootNode);
sb.append("\n remainingCACerts: " + remainingCACerts); sb.append("\n remainingCACerts: ").append(remainingCACerts);
sb.append("\n crlSign: " + crlSign); sb.append("\n crlSign: ").append(crlSign);
sb.append("\n init: " + init); sb.append("\n init: ").append(init);
sb.append("\n]\n"); sb.append("\n]\n");
} catch (Exception e) {
if (debug != null) {
debug.println("ReverseState.toString() unexpected exception");
e.printStackTrace();
}
}
return sb.toString(); return sb.toString();
} }
/** /**
* Initialize the state. * Initialize the state.
* *
* @param maxPathLen The maximum number of CA certs in a path, where -1 * @param buildParams builder parameters
* means unlimited and 0 means only a single EE cert is allowed.
* @param explicitPolicyRequired True, if explicit policy is required.
* @param policyMappingInhibited True, if policy mapping is inhibited.
* @param anyPolicyInhibited True, if any policy is inhibited.
* @param certPathCheckers the list of user-defined PKIXCertPathCheckers
*/ */
public void initState(int maxPathLen, boolean explicitPolicyRequired, public void initState(BuilderParams buildParams)
boolean policyMappingInhibited, boolean anyPolicyInhibited,
List<PKIXCertPathChecker> certPathCheckers)
throws CertPathValidatorException throws CertPathValidatorException
{ {
/* /*
...@@ -165,60 +155,52 @@ class ReverseState implements State { ...@@ -165,60 +155,52 @@ class ReverseState implements State {
* Note that -1 maxPathLen implies unlimited. * Note that -1 maxPathLen implies unlimited.
* 0 implies only an EE cert is acceptable. * 0 implies only an EE cert is acceptable.
*/ */
remainingCACerts = (maxPathLen == -1 ? Integer.MAX_VALUE : maxPathLen); int maxPathLen = buildParams.maxPathLength();
remainingCACerts = (maxPathLen == -1) ? Integer.MAX_VALUE
: maxPathLen;
/* Initialize explicit policy state variable */ /* Initialize explicit policy state variable */
if (explicitPolicyRequired) { if (buildParams.explicitPolicyRequired()) {
explicitPolicy = 0; explicitPolicy = 0;
} else { } else {
// unconstrained if maxPathLen is -1, // unconstrained if maxPathLen is -1,
// otherwise, we want to initialize this to the value of the // otherwise, we want to initialize this to the value of the
// longest possible path + 1 (i.e. maxpathlen + finalcert + 1) // longest possible path + 1 (i.e. maxpathlen + finalcert + 1)
explicitPolicy = (maxPathLen == -1) explicitPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
? maxPathLen
: maxPathLen + 2;
} }
/* Initialize policy mapping state variable */ /* Initialize policy mapping state variable */
if (policyMappingInhibited) { if (buildParams.policyMappingInhibited()) {
policyMapping = 0; policyMapping = 0;
} else { } else {
policyMapping = (maxPathLen == -1) policyMapping = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
? maxPathLen
: maxPathLen + 2;
} }
/* Initialize inhibit any policy state variable */ /* Initialize inhibit any policy state variable */
if (anyPolicyInhibited) { if (buildParams.anyPolicyInhibited()) {
inhibitAnyPolicy = 0; inhibitAnyPolicy = 0;
} else { } else {
inhibitAnyPolicy = (maxPathLen == -1) inhibitAnyPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
? maxPathLen
: maxPathLen + 2;
} }
/* Initialize certIndex */ /* Initialize certIndex */
certIndex = 1; certIndex = 1;
/* Initialize policy tree */ /* Initialize policy tree */
Set<String> initExpPolSet = new HashSet<String>(1); Set<String> initExpPolSet = new HashSet<>(1);
initExpPolSet.add(PolicyChecker.ANY_POLICY); initExpPolSet.add(PolicyChecker.ANY_POLICY);
rootNode = new PolicyNodeImpl rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null,
(null, PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false); false, initExpPolSet, false);
/* /*
* Initialize each user-defined checker * Initialize each user-defined checker
* Shallow copy the checkers
*/ */
if (certPathCheckers != null) { userCheckers = new ArrayList<>(buildParams.certPathCheckers());
/* Shallow copy the checkers */ /* initialize each checker (just in case) */
userCheckers = new ArrayList<PKIXCertPathChecker>(certPathCheckers); for (PKIXCertPathChecker checker : userCheckers) {
/* initialize each checker (just in case) */ checker.init(false);
for (PKIXCertPathChecker checker : certPathCheckers) {
checker.init(false);
}
} else {
userCheckers = new ArrayList<PKIXCertPathChecker>();
} }
/* Start by trusting the cert to sign CRLs */ /* Start by trusting the cert to sign CRLs */
...@@ -231,8 +213,9 @@ class ReverseState implements State { ...@@ -231,8 +213,9 @@ class ReverseState implements State {
* Update the state with the specified trust anchor. * Update the state with the specified trust anchor.
* *
* @param anchor the most-trusted CA * @param anchor the most-trusted CA
* @param buildParams builder parameters
*/ */
public void updateState(TrustAnchor anchor) public void updateState(TrustAnchor anchor, BuilderParams buildParams)
throws CertificateException, IOException, CertPathValidatorException throws CertificateException, IOException, CertPathValidatorException
{ {
trustAnchor = anchor; trustAnchor = anchor;
...@@ -244,14 +227,26 @@ class ReverseState implements State { ...@@ -244,14 +227,26 @@ class ReverseState implements State {
updateState(anchor.getCAPublicKey(), caName); updateState(anchor.getCAPublicKey(), caName);
} }
// The user specified AlgorithmChecker may not be // The user specified AlgorithmChecker and RevocationChecker may not be
// able to set the trust anchor until now. // able to set the trust anchor until now.
boolean revCheckerAdded = false;
for (PKIXCertPathChecker checker : userCheckers) { for (PKIXCertPathChecker checker : userCheckers) {
if (checker instanceof AlgorithmChecker) { if (checker instanceof AlgorithmChecker) {
((AlgorithmChecker)checker).trySetTrustAnchor(anchor); ((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
} else if (checker instanceof RevocationChecker) {
((RevocationChecker)checker).init(anchor, buildParams);
((RevocationChecker)checker).init(false);
revCheckerAdded = true;
} }
} }
// only create a RevocationChecker if revocation is enabled and
// a PKIXRevocationChecker has not already been added
if (buildParams.revocationEnabled() && !revCheckerAdded) {
revChecker = new RevocationChecker(anchor, buildParams);
revChecker.init(false);
}
init = false; init = false;
} }
...@@ -310,7 +305,7 @@ class ReverseState implements State { ...@@ -310,7 +305,7 @@ class ReverseState implements State {
subjKeyId = icert.getSubjectKeyIdentifierExtension(); subjKeyId = icert.getSubjectKeyIdentifierExtension();
/* update crlSign */ /* update crlSign */
crlSign = CrlRevocationChecker.certCanSignCrl(cert); crlSign = RevocationChecker.certCanSignCrl(cert);
/* update current name constraints */ /* update current name constraints */
if (nc != null) { if (nc != null) {
...@@ -349,6 +344,7 @@ class ReverseState implements State { ...@@ -349,6 +344,7 @@ class ReverseState implements State {
* *
* @return boolean flag indicating if key lacking parameters encountered. * @return boolean flag indicating if key lacking parameters encountered.
*/ */
@Override
public boolean keyParamsNeeded() { public boolean keyParamsNeeded() {
/* when building in reverse, we immediately get parameters needed /* when building in reverse, we immediately get parameters needed
* or else throw an exception * or else throw an exception
...@@ -365,6 +361,7 @@ class ReverseState implements State { ...@@ -365,6 +361,7 @@ class ReverseState implements State {
* because some of them (e.g., subjKeyId) will * because some of them (e.g., subjKeyId) will
* not have their contents modified by subsequent calls to updateState. * not have their contents modified by subsequent calls to updateState.
*/ */
@Override
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
public Object clone() { public Object clone() {
try { try {
......
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,345 +25,526 @@ ...@@ -25,345 +25,526 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.AccessController;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivilegedAction;
import java.security.PublicKey;
import java.security.Security;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.Extension;
import java.security.cert.*;
import java.security.interfaces.DSAPublicKey;
import java.util.Arrays; import java.util.Arrays;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Iterator; import javax.security.auth.x500.X500Principal;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException; import static sun.security.provider.certpath.OCSP.*;
import java.security.PublicKey; import sun.security.provider.certpath.PKIX.ValidatorParams;
import java.security.cert.*; import sun.security.action.GetPropertyAction;
import java.security.cert.CertPathValidatorException.BasicReason; import sun.security.x509.*;
import java.security.interfaces.DSAPublicKey; import static sun.security.x509.PKIXExtensions.*;
import sun.security.util.Debug; import sun.security.util.Debug;
import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension; class RevocationChecker extends PKIXRevocationChecker {
import sun.security.x509.CRLDistributionPointsExtension;
import sun.security.x509.DistributionPoint;
import sun.security.x509.GeneralName;
import sun.security.x509.GeneralNames;
import sun.security.x509.PKIXExtensions;
import sun.security.x509.X500Name;
import sun.security.x509.X509CertImpl;
import sun.security.x509.X509CRLEntryImpl;
/**
* CrlRevocationChecker is a <code>PKIXCertPathChecker</code> that checks
* revocation status information on a PKIX certificate using CRLs obtained
* from one or more <code>CertStores</code>. This is based on section 6.3
* of RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt).
*
* @since 1.4
* @author Seth Proctor
* @author Steve Hanna
*/
class CrlRevocationChecker extends PKIXCertPathChecker {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private final TrustAnchor mAnchor;
private final List<CertStore> mStores;
private final String mSigProvider;
private final Date mCurrentTime;
private PublicKey mPrevPubKey;
private boolean mCRLSignFlag;
private HashSet<X509CRL> mPossibleCRLs;
private HashSet<X509CRL> mApprovedCRLs;
private final PKIXParameters mParams;
private static final boolean [] mCrlSignUsage =
{ false, false, false, false, false, false, true };
private static final boolean[] ALL_REASONS =
{true, true, true, true, true, true, true, true, true};
private boolean mOnlyEECert = false;
// Maximum clock skew in milliseconds (15 minutes) allowed when checking private TrustAnchor anchor;
// validity of CRLs private ValidatorParams params;
private static final long MAX_CLOCK_SKEW = 900000; private boolean onlyEE;
private boolean softFail;
private boolean crlDP;
private URI responderURI;
private X509Certificate responderCert;
private List<CertStore> certStores;
private Map<X509Certificate, byte[]> ocspStapled;
private List<Extension> ocspExtensions;
private boolean legacy;
/** // state variables
* Creates a <code>CrlRevocationChecker</code>. private X509Certificate issuerCert;
* private PublicKey prevPubKey;
* @param anchor anchor selected to validate the target certificate private boolean crlSignFlag;
* @param params <code>PKIXParameters</code> to be used for
* finding certificates and CRLs, etc. private enum Mode { PREFER_OCSP, PREFER_CRLS, ONLY_CRLS };
*/ private Mode mode = Mode.PREFER_OCSP;
CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params)
private static class RevocationProperties {
boolean onlyEE;
boolean ocspEnabled;
boolean crlDPEnabled;
String ocspUrl;
String ocspSubject;
String ocspIssuer;
String ocspSerial;
}
RevocationChecker() {
legacy = false;
}
RevocationChecker(TrustAnchor anchor, ValidatorParams params)
throws CertPathValidatorException throws CertPathValidatorException
{ {
this(anchor, params, null); legacy = true;
init(anchor, params);
} }
/** void init(TrustAnchor anchor, ValidatorParams params)
* Creates a <code>CrlRevocationChecker</code>, allowing throws CertPathValidatorException
* extra certificates to be supplied beyond those contained
* in the <code>PKIXParameters</code>.
*
* @param anchor anchor selected to validate the target certificate
* @param params <code>PKIXParameters</code> to be used for
* finding certificates and CRLs, etc.
* @param certs a <code>Collection</code> of certificates
* that may be useful, beyond those available
* through <code>params</code> (<code>null</code>
* if none)
*/
CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
Collection<X509Certificate> certs) throws CertPathValidatorException
{ {
this(anchor, params, certs, false); RevocationProperties rp = getRevocationProperties();
URI uri = getOCSPResponder();
responderURI = (uri == null) ? toURI(rp.ocspUrl) : uri;
X509Certificate cert = getOCSPResponderCert();
responderCert = (cert == null)
? getResponderCert(rp, params.trustAnchors(),
params.certStores())
: cert;
Set<Option> options = getOptions();
for (Option option : options) {
switch (option) {
case ONLY_END_ENTITY:
case PREFER_CRLS:
case SOFT_FAIL:
break;
default:
throw new CertPathValidatorException(
"Unrecognized revocation parameter option: " + option);
}
}
// set mode, only end entity flag
if (legacy) {
mode = (rp.ocspEnabled) ? Mode.PREFER_OCSP : Mode.ONLY_CRLS;
onlyEE = rp.onlyEE;
} else {
if (options.contains(Option.PREFER_CRLS)) {
mode = Mode.PREFER_CRLS;
}
onlyEE = options.contains(Option.ONLY_END_ENTITY);
}
softFail = options.contains(Option.SOFT_FAIL);
if (legacy) {
crlDP = rp.crlDPEnabled;
} else {
crlDP = true;
}
ocspStapled = getOCSPStapledResponses();
ocspExtensions = getOCSPExtensions();
this.anchor = anchor;
this.params = params;
this.certStores = new ArrayList<>(params.certStores());
try {
this.certStores.add(CertStore.getInstance("Collection",
new CollectionCertStoreParameters(params.certificates())));
} catch (InvalidAlgorithmParameterException |
NoSuchAlgorithmException e) {
// should never occur but not necessarily fatal, so log it,
// ignore and continue
if (debug != null) {
debug.println("RevocationChecker: " +
"error creating Collection CertStore: " + e);
}
}
} }
CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params, private static URI toURI(String uriString)
Collection<X509Certificate> certs, boolean onlyEECert) throws CertPathValidatorException
throws CertPathValidatorException { {
mAnchor = anchor; try {
mParams = params; if (uriString != null) {
mStores = new ArrayList<CertStore>(params.getCertStores()); return new URI(uriString);
mSigProvider = params.getSigProvider(); }
if (certs != null) { return null;
try { } catch (URISyntaxException e) {
mStores.add(CertStore.getInstance("Collection", throw new CertPathValidatorException(
new CollectionCertStoreParameters(certs))); "cannot parse ocsp.responderURL property", e);
} catch (Exception e) { }
// should never occur but not necessarily fatal, so log it, }
// ignore and continue
if (debug != null) { private static RevocationProperties getRevocationProperties() {
debug.println("CrlRevocationChecker: " + return AccessController.doPrivileged(
"error creating Collection CertStore: " + e); new PrivilegedAction<RevocationProperties>() {
public RevocationProperties run() {
RevocationProperties rp = new RevocationProperties();
String onlyEE = Security.getProperty(
"com.sun.security.onlyCheckRevocationOfEECert");
rp.onlyEE = onlyEE != null
&& onlyEE.equalsIgnoreCase("true");
String ocspEnabled = Security.getProperty("ocsp.enable");
rp.ocspEnabled = ocspEnabled != null
&& ocspEnabled.equalsIgnoreCase("true");
rp.ocspUrl = Security.getProperty("ocsp.responderURL");
rp.ocspSubject
= Security.getProperty("ocsp.responderCertSubjectName");
rp.ocspIssuer
= Security.getProperty("ocsp.responderCertIssuerName");
rp.ocspSerial
= Security.getProperty("ocsp.responderCertSerialNumber");
rp.crlDPEnabled
= Boolean.getBoolean("com.sun.security.enableCRLDP");
return rp;
} }
} }
);
}
private static X509Certificate getResponderCert(RevocationProperties rp,
Set<TrustAnchor> anchors,
List<CertStore> stores)
throws CertPathValidatorException
{
if (rp.ocspSubject != null) {
return getResponderCert(rp.ocspSubject, anchors, stores);
} else if (rp.ocspIssuer != null && rp.ocspSerial != null) {
return getResponderCert(rp.ocspIssuer, rp.ocspSerial,
anchors, stores);
} else if (rp.ocspIssuer != null || rp.ocspSerial != null) {
throw new CertPathValidatorException(
"Must specify both ocsp.responderCertIssuerName and " +
"ocsp.responderCertSerialNumber properties");
} }
Date testDate = params.getDate(); return null;
mCurrentTime = (testDate != null ? testDate : new Date());
mOnlyEECert = onlyEECert;
init(false);
} }
/** private static X509Certificate getResponderCert(String subject,
* Initializes the internal state of the checker from parameters Set<TrustAnchor> anchors,
* specified in the constructor List<CertStore> stores)
*/ throws CertPathValidatorException
public void init(boolean forward) throws CertPathValidatorException
{ {
if (!forward) { X509CertSelector sel = new X509CertSelector();
if (mAnchor != null) { try {
if (mAnchor.getCAPublicKey() != null) { sel.setSubject(new X500Principal(subject));
mPrevPubKey = mAnchor.getCAPublicKey(); } catch (IllegalArgumentException e) {
} else { throw new CertPathValidatorException(
mPrevPubKey = mAnchor.getTrustedCert().getPublicKey(); "cannot parse ocsp.responderCertSubjectName property", e);
}
return getResponderCert(sel, anchors, stores);
}
private static X509Certificate getResponderCert(String issuer,
String serial,
Set<TrustAnchor> anchors,
List<CertStore> stores)
throws CertPathValidatorException
{
X509CertSelector sel = new X509CertSelector();
try {
sel.setIssuer(new X500Principal(issuer));
} catch (IllegalArgumentException e) {
throw new CertPathValidatorException(
"cannot parse ocsp.responderCertIssuerName property", e);
}
try {
sel.setSerialNumber(new BigInteger(stripOutSeparators(serial), 16));
} catch (NumberFormatException e) {
throw new CertPathValidatorException(
"cannot parse ocsp.responderCertSerialNumber property", e);
}
return getResponderCert(sel, anchors, stores);
}
private static X509Certificate getResponderCert(X509CertSelector sel,
Set<TrustAnchor> anchors,
List<CertStore> stores)
throws CertPathValidatorException
{
// first check TrustAnchors
for (TrustAnchor anchor : anchors) {
X509Certificate cert = anchor.getTrustedCert();
if (cert == null) {
continue;
}
if (sel.match(cert)) {
return cert;
}
}
// now check CertStores
for (CertStore store : stores) {
try {
Collection<? extends Certificate> certs =
store.getCertificates(sel);
if (!certs.isEmpty()) {
return (X509Certificate)certs.iterator().next();
} }
} else { } catch (CertStoreException e) {
mPrevPubKey = null; // ignore and try next CertStore
if (debug != null) {
debug.println("CertStore exception:" + e);
}
continue;
} }
mCRLSignFlag = true; }
throw new CertPathValidatorException(
"Cannot find the responder's certificate " +
"(set using the OCSP security properties).");
}
@Override
public void init(boolean forward) throws CertPathValidatorException {
if (forward) {
throw new
CertPathValidatorException("forward checking not supported");
} else { } else {
throw new CertPathValidatorException("forward checking " if (anchor != null) {
+ "not supported"); issuerCert = anchor.getTrustedCert();
prevPubKey = (issuerCert != null) ? issuerCert.getPublicKey()
: anchor.getCAPublicKey();
}
crlSignFlag = true;
} }
} }
@Override
public boolean isForwardCheckingSupported() { public boolean isForwardCheckingSupported() {
return false; return false;
} }
@Override
public Set<String> getSupportedExtensions() { public Set<String> getSupportedExtensions() {
return null; return null;
} }
/** @Override
* Performs the revocation status check on the certificate using
* its internal state.
*
* @param cert the Certificate
* @param unresolvedCritExts a Collection of the unresolved critical
* extensions
* @exception CertPathValidatorException Exception thrown if
* certificate does not verify
*/
public void check(Certificate cert, Collection<String> unresolvedCritExts) public void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException throws CertPathValidatorException
{ {
X509Certificate currCert = (X509Certificate) cert; X509Certificate xcert = (X509Certificate)cert;
verifyRevocationStatus(currCert, mPrevPubKey, mCRLSignFlag, true); if (onlyEE && xcert.getBasicConstraints() != -1) {
if (debug != null) {
// Make new public key if parameters are missing debug.println("Skipping revocation check, not end entity cert");
PublicKey cKey = currCert.getPublicKey(); }
if (cKey instanceof DSAPublicKey && } else {
((DSAPublicKey)cKey).getParams() == null) { check(xcert, unresolvedCritExts, prevPubKey, crlSignFlag);
// cKey needs to inherit DSA parameters from prev key }
cKey = BasicChecker.makeInheritedParamsKey(cKey, mPrevPubKey); updateState(xcert);
}
mPrevPubKey = cKey;
mCRLSignFlag = certCanSignCrl(currCert);
} }
/** void check(X509Certificate xcert, Collection<String> unresolvedCritExts,
* Performs the revocation status check on the certificate using PublicKey pubKey, boolean crlSignFlag)
* the provided state variables, as well as the constant internal throws CertPathValidatorException
* data.
*
* @param currCert the Certificate
* @param prevKey the previous PublicKey in the chain
* @param signFlag a boolean as returned from the last call, or true
* if this is the first cert in the chain
* @return a boolean specifying if the cert is allowed to vouch for the
* validity of a CRL for the next iteration
* @exception CertPathValidatorException Exception thrown if
* certificate does not verify.
*/
public boolean check(X509Certificate currCert, PublicKey prevKey,
boolean signFlag) throws CertPathValidatorException
{ {
verifyRevocationStatus(currCert, prevKey, signFlag, true); try {
return certCanSignCrl(currCert); switch (mode) {
case PREFER_OCSP:
checkOCSP(xcert, unresolvedCritExts);
break;
case PREFER_CRLS:
case ONLY_CRLS:
checkCRLs(xcert, unresolvedCritExts, null,
pubKey, crlSignFlag);
break;
}
} catch (CertPathValidatorException e) {
if (e.getReason() == BasicReason.REVOKED) {
throw e;
}
CertPathValidatorException cause = e;
if (softFail && e instanceof NetworkFailureException) {
if (mode == Mode.ONLY_CRLS) return;
}
// Rethrow the exception if ONLY_CRLS
if (mode == Mode.ONLY_CRLS) {
throw e;
}
// Otherwise, failover
if (debug != null) {
debug.println("RevocationChecker.check() " + e.getMessage());
debug.println("RevocationChecker.check() preparing to failover");
}
try {
switch (mode) {
case PREFER_OCSP:
checkCRLs(xcert, unresolvedCritExts, null,
pubKey, crlSignFlag);
break;
case PREFER_CRLS:
checkOCSP(xcert, unresolvedCritExts);
break;
}
} catch (CertPathValidatorException x) {
if (debug != null) {
debug.println("RevocationChecker.check() failover failed");
debug.println("RevocationChecker.check() " + x.getMessage());
}
if (x.getReason() == BasicReason.REVOKED) {
throw x;
}
if (cause != null) {
if (softFail && cause instanceof NetworkFailureException) {
return;
} else {
cause.addSuppressed(x);
throw cause;
}
}
if (softFail && x instanceof NetworkFailureException) {
return;
}
throw x;
}
}
} }
/** private void updateState(X509Certificate cert)
* Checks that a cert can be used to verify a CRL. throws CertPathValidatorException
* {
* @param currCert an X509Certificate to check issuerCert = cert;
* @return a boolean specifying if the cert is allowed to vouch for the
* validity of a CRL // Make new public key if parameters are missing
*/ PublicKey pubKey = cert.getPublicKey();
static boolean certCanSignCrl(X509Certificate currCert) { if (pubKey instanceof DSAPublicKey &&
// if the cert doesn't include the key usage ext, or ((DSAPublicKey)pubKey).getParams() == null) {
// the key usage ext asserts cRLSigning, return true, // pubKey needs to inherit DSA parameters from prev key
// otherwise return false. pubKey = BasicChecker.makeInheritedParamsKey(pubKey, prevPubKey);
boolean[] kbools = currCert.getKeyUsage();
if (kbools != null) {
return kbools[6];
} }
return false; prevPubKey = pubKey;
crlSignFlag = certCanSignCrl(cert);
} }
/** // Maximum clock skew in milliseconds (15 minutes) allowed when checking
* Internal method to start the verification of a cert // validity of CRLs
*/ private static final long MAX_CLOCK_SKEW = 900000;
private void verifyRevocationStatus(X509Certificate currCert, private void checkCRLs(X509Certificate cert,
PublicKey prevKey, boolean signFlag, boolean allowSeparateKey) Collection<String> unresolvedCritExts,
Set<X509Certificate> stackedCerts,
PublicKey pubKey, boolean signFlag)
throws CertPathValidatorException throws CertPathValidatorException
{ {
verifyRevocationStatus(currCert, prevKey, signFlag, checkCRLs(cert, pubKey, signFlag, true,
allowSeparateKey, null, mParams.getTrustAnchors()); stackedCerts, params.trustAnchors());
} }
/** private void checkCRLs(X509Certificate cert, PublicKey prevKey,
* Internal method to start the verification of a cert boolean signFlag, boolean allowSeparateKey,
* @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s> Set<X509Certificate> stackedCerts,
* whose revocation status depends on the Set<TrustAnchor> anchors)
* non-revoked status of this cert. To avoid throws CertPathValidatorException
* circular dependencies, we assume they're {
* revoked while checking the revocation
* status of this cert.
* @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
*/
private void verifyRevocationStatus(X509Certificate currCert,
PublicKey prevKey, boolean signFlag, boolean allowSeparateKey,
Set<X509Certificate> stackedCerts,
Set<TrustAnchor> trustAnchors) throws CertPathValidatorException {
String msg = "revocation status";
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus()" + debug.println("RevocationChecker.checkCRLs()" +
" ---checking " + msg + "..."); " ---checking revocation status ...");
}
if (mOnlyEECert && currCert.getBasicConstraints() != -1) {
if (debug != null) {
debug.println("Skipping revocation check, not end entity cert");
}
return;
} }
// reject circular dependencies - RFC 3280 is not explicit on how // reject circular dependencies - RFC 3280 is not explicit on how
// to handle this, so we feel it is safest to reject them until // to handle this, so we feel it is safest to reject them until
// the issue is resolved in the PKIX WG. // the issue is resolved in the PKIX WG.
if ((stackedCerts != null) && stackedCerts.contains(currCert)) { if (stackedCerts != null && stackedCerts.contains(cert)) {
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus()" + debug.println("RevocationChecker.checkCRLs()" +
" circular dependency"); " circular dependency");
} }
throw new CertPathValidatorException throw new CertPathValidatorException
("Could not determine revocation status", null, null, -1, ("Could not determine revocation status", null, null, -1,
BasicReason.UNDETERMINED_REVOCATION_STATUS); BasicReason.UNDETERMINED_REVOCATION_STATUS);
} }
// init the state for this run Set<X509CRL> possibleCRLs = new HashSet<>();
mPossibleCRLs = new HashSet<X509CRL>(); Set<X509CRL> approvedCRLs = new HashSet<>();
mApprovedCRLs = new HashSet<X509CRL>(); X509CRLSelector sel = new X509CRLSelector();
boolean[] reasonsMask = new boolean[9]; sel.setCertificateChecking(cert);
CertPathHelper.setDateAndTime(sel, params.date(), MAX_CLOCK_SKEW);
try {
X509CRLSelector sel = new X509CRLSelector();
sel.setCertificateChecking(currCert);
CertPathHelper.setDateAndTime(sel, mCurrentTime, MAX_CLOCK_SKEW);
for (CertStore mStore : mStores) { // First, check cached CRLs
for (java.security.cert.CRL crl : mStore.getCRLs(sel)) { for (CertStore store : certStores) {
mPossibleCRLs.add((X509CRL)crl); try {
for (CRL crl : store.getCRLs(sel)) {
possibleCRLs.add((X509CRL)crl);
} }
} catch (CertStoreException e) {
// XXX ignore?
} }
DistributionPointFetcher store =
DistributionPointFetcher.getInstance();
// all CRLs returned by the DP Fetcher have also been verified
mApprovedCRLs.addAll(store.getCRLs(sel, signFlag, prevKey,
mSigProvider, mStores, reasonsMask, trustAnchors,
mParams.getDate()));
} catch (Exception e) {
if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus() "
+ "unexpected exception: " + e.getMessage());
}
throw new CertPathValidatorException(e);
} }
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus() " + debug.println("RevocationChecker.checkCRLs() " +
"crls.size() = " + mPossibleCRLs.size()); "possible crls.size() = " + possibleCRLs.size());
} }
if (!mPossibleCRLs.isEmpty()) { boolean[] reasonsMask = new boolean[9];
if (!possibleCRLs.isEmpty()) {
// Now that we have a list of possible CRLs, see which ones can // Now that we have a list of possible CRLs, see which ones can
// be approved // be approved
mApprovedCRLs.addAll(verifyPossibleCRLs(mPossibleCRLs, currCert, approvedCRLs.addAll(verifyPossibleCRLs(possibleCRLs, cert, prevKey,
signFlag, prevKey, reasonsMask, trustAnchors)); signFlag, reasonsMask,
anchors));
} }
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus() " + debug.println("RevocationChecker.checkCRLs() " +
"approved crls.size() = " + mApprovedCRLs.size()); "approved crls.size() = " + approvedCRLs.size());
} }
// make sure that we have at least one CRL that _could_ cover // make sure that we have at least one CRL that _could_ cover
// the certificate in question and all reasons are covered // the certificate in question and all reasons are covered
if (mApprovedCRLs.isEmpty() || if (!approvedCRLs.isEmpty() &&
!Arrays.equals(reasonsMask, ALL_REASONS)) { Arrays.equals(reasonsMask, ALL_REASONS))
if (allowSeparateKey) { {
verifyWithSeparateSigningKey(currCert, prevKey, signFlag, checkApprovedCRLs(cert, approvedCRLs);
stackedCerts); } else {
return; // Check Distribution Points
// all CRLs returned by the DP Fetcher have also been verified
try {
if (crlDP) {
approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
sel, signFlag, prevKey,
params.sigProvider(), certStores,
reasonsMask, anchors, params.date()));
}
} catch (CertStoreException e) {
if (debug != null) {
debug.println("RevocationChecker.checkCRLs() " +
"unexpected exception: " + e.getMessage());
}
throw new CertPathValidatorException(e);
}
if (!approvedCRLs.isEmpty() &&
Arrays.equals(reasonsMask, ALL_REASONS))
{
checkApprovedCRLs(cert, approvedCRLs);
} else { } else {
throw new CertPathValidatorException if (allowSeparateKey) {
("Could not determine revocation status", null, null, -1, verifyWithSeparateSigningKey(cert, prevKey, signFlag,
BasicReason.UNDETERMINED_REVOCATION_STATUS); stackedCerts);
return;
} else {
throw new CertPathValidatorException
("Could not determine revocation status", null, null, -1,
BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
} }
} }
}
private void checkApprovedCRLs(X509Certificate cert,
Set<X509CRL> approvedCRLs)
throws CertPathValidatorException
{
// See if the cert is in the set of approved crls. // See if the cert is in the set of approved crls.
if (debug != null) { if (debug != null) {
BigInteger sn = currCert.getSerialNumber(); BigInteger sn = cert.getSerialNumber();
debug.println("CrlRevocationChecker.verifyRevocationStatus() " + debug.println("RevocationChecker.checkApprovedCRLs() " +
"starting the final sweep..."); "starting the final sweep...");
debug.println("CrlRevocationChecker.verifyRevocationStatus" + debug.println("RevocationChecker.checkApprovedCRLs()" +
" cert SN: " + sn.toString()); " cert SN: " + sn.toString());
} }
CRLReason reasonCode = CRLReason.UNSPECIFIED; CRLReason reasonCode = CRLReason.UNSPECIFIED;
X509CRLEntryImpl entry = null; X509CRLEntryImpl entry = null;
for (X509CRL crl : mApprovedCRLs) { for (X509CRL crl : approvedCRLs) {
X509CRLEntry e = crl.getRevokedCertificate(currCert); X509CRLEntry e = crl.getRevokedCertificate(cert);
if (e != null) { if (e != null) {
try { try {
entry = X509CRLEntryImpl.toImpl(e); entry = X509CRLEntryImpl.toImpl(e);
...@@ -371,7 +552,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -371,7 +552,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
throw new CertPathValidatorException(ce); throw new CertPathValidatorException(ce);
} }
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus" debug.println("RevocationChecker.checkApprovedCRLs()"
+ " CRL entry: " + entry.toString()); + " CRL entry: " + entry.toString());
} }
...@@ -383,10 +564,8 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -383,10 +564,8 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
Set<String> unresCritExts = entry.getCriticalExtensionOIDs(); Set<String> unresCritExts = entry.getCriticalExtensionOIDs();
if (unresCritExts != null && !unresCritExts.isEmpty()) { if (unresCritExts != null && !unresCritExts.isEmpty()) {
/* remove any that we will process */ /* remove any that we will process */
unresCritExts.remove unresCritExts.remove(ReasonCode_Id.toString());
(PKIXExtensions.ReasonCode_Id.toString()); unresCritExts.remove(CertificateIssuer_Id.toString());
unresCritExts.remove
(PKIXExtensions.CertificateIssuer_Id.toString());
if (!unresCritExts.isEmpty()) { if (!unresCritExts.isEmpty()) {
if (debug != null) { if (debug != null) {
debug.println("Unrecognized " debug.println("Unrecognized "
...@@ -412,6 +591,205 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -412,6 +591,205 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
} }
} }
private void checkOCSP(X509Certificate cert,
Collection<String> unresolvedCritExts)
throws CertPathValidatorException
{
X509CertImpl currCert = null;
try {
currCert = X509CertImpl.toImpl(cert);
} catch (CertificateException ce) {
throw new CertPathValidatorException(ce);
}
URI responderURI = (this.responderURI != null)
? this.responderURI : getOCSPServerURI(currCert);
X509Certificate respCert = (responderCert == null) ? issuerCert
: responderCert;
// The algorithm constraints of the OCSP trusted responder certificate
// does not need to be checked in this code. The constraints will be
// checked when the responder's certificate is validated.
OCSPResponse response = null;
CertId certId = null;
try {
certId = new CertId(issuerCert, currCert.getSerialNumberObject());
// check if there is a stapled OCSP response available
byte[] responseBytes = ocspStapled.get(cert);
if (responseBytes != null) {
if (debug != null) {
debug.println("Found stapled OCSP response");
}
response = new OCSPResponse(responseBytes);
// verify the response
byte[] nonce = null;
for (Extension ext : ocspExtensions) {
if (ext.getId().equals("1.3.6.1.5.5.7.48.1.2")) {
nonce = ext.getValue();
}
}
response.verify(Collections.singletonList(certId), respCert,
params.date(), nonce);
} else {
response = OCSP.check(Collections.singletonList(certId),
responderURI, respCert, params.date(),
ocspExtensions);
}
} catch (IOException e) {
throw new CertPathValidatorException(e);
}
RevocationStatus rs =
(RevocationStatus)response.getSingleResponse(certId);
RevocationStatus.CertStatus certStatus = rs.getCertStatus();
if (certStatus == RevocationStatus.CertStatus.REVOKED) {
Throwable t = new CertificateRevokedException(
rs.getRevocationTime(), rs.getRevocationReason(),
respCert.getSubjectX500Principal(), rs.getSingleExtensions());
throw new CertPathValidatorException(t.getMessage(), t, null,
-1, BasicReason.REVOKED);
} else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
throw new CertPathValidatorException(
"Certificate's revocation status is unknown", null,
params.certPath(), -1,
BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
/*
* Removes any non-hexadecimal characters from a string.
*/
private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
private static String stripOutSeparators(String value) {
char[] chars = value.toCharArray();
StringBuilder hexNumber = new StringBuilder();
for (int i = 0; i < chars.length; i++) {
if (HEX_DIGITS.indexOf(chars[i]) != -1) {
hexNumber.append(chars[i]);
}
}
return hexNumber.toString();
}
private static URI getOCSPServerURI(X509CertImpl cert)
throws CertPathValidatorException
{
// Examine the certificate's AuthorityInfoAccess extension
AuthorityInfoAccessExtension aia =
cert.getAuthorityInfoAccessExtension();
if (aia == null) {
throw new CertPathValidatorException(
"Must specify the location of an OCSP Responder");
}
List<AccessDescription> descriptions = aia.getAccessDescriptions();
for (AccessDescription description : descriptions) {
if (description.getAccessMethod().equals((Object)
AccessDescription.Ad_OCSP_Id)) {
GeneralName generalName = description.getAccessLocation();
if (generalName.getType() == GeneralNameInterface.NAME_URI) {
URIName uri = (URIName)generalName.getName();
return uri.getURI();
}
}
}
throw new CertPathValidatorException(
"Cannot find the location of the OCSP Responder");
}
/**
* Checks that a cert can be used to verify a CRL.
*
* @param cert an X509Certificate to check
* @return a boolean specifying if the cert is allowed to vouch for the
* validity of a CRL
*/
static boolean certCanSignCrl(X509Certificate cert) {
// if the cert doesn't include the key usage ext, or
// the key usage ext asserts cRLSigning, return true,
// otherwise return false.
boolean[] keyUsage = cert.getKeyUsage();
if (keyUsage != null) {
return keyUsage[6];
}
return false;
}
/**
* Internal method that verifies a set of possible_crls,
* and sees if each is approved, based on the cert.
*
* @param crls a set of possible CRLs to test for acceptability
* @param cert the certificate whose revocation status is being checked
* @param signFlag <code>true</code> if prevKey was trusted to sign CRLs
* @param prevKey the public key of the issuer of cert
* @param reasonsMask the reason code mask
* @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s>
* @return a collection of approved crls (or an empty collection)
*/
private static final boolean[] ALL_REASONS =
{true, true, true, true, true, true, true, true, true};
private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls,
X509Certificate cert,
PublicKey prevKey,
boolean signFlag,
boolean[] reasonsMask,
Set<TrustAnchor> anchors)
throws CertPathValidatorException
{
try {
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
if (debug != null) {
debug.println("RevocationChecker.verifyPossibleCRLs: " +
"Checking CRLDPs for "
+ certImpl.getSubjectX500Principal());
}
CRLDistributionPointsExtension ext =
certImpl.getCRLDistributionPointsExtension();
List<DistributionPoint> points = null;
if (ext == null) {
// assume a DP with reasons and CRLIssuer fields omitted
// and a DP name of the cert issuer.
// TODO add issuerAltName too
X500Name certIssuer = (X500Name)certImpl.getIssuerDN();
DistributionPoint point = new DistributionPoint(
new GeneralNames().add(new GeneralName(certIssuer)),
null, null);
points = Collections.singletonList(point);
} else {
points = ext.get(CRLDistributionPointsExtension.POINTS);
}
Set<X509CRL> results = new HashSet<>();
for (DistributionPoint point : points) {
for (X509CRL crl : crls) {
if (DistributionPointFetcher.verifyCRL(
certImpl, point, crl, reasonsMask, signFlag,
prevKey, params.sigProvider(), anchors,
certStores, params.date()))
{
results.add(crl);
}
}
if (Arrays.equals(reasonsMask, ALL_REASONS))
break;
}
return results;
} catch (CertificateException | CRLException | IOException e) {
if (debug != null) {
debug.println("Exception while verifying CRL: "+e.getMessage());
e.printStackTrace();
}
return Collections.emptySet();
}
}
/** /**
* We have a cert whose revocation status couldn't be verified by * We have a cert whose revocation status couldn't be verified by
* a CRL issued by the cert that issued the CRL. See if we can * a CRL issued by the cert that issued the CRL. See if we can
...@@ -434,23 +812,26 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -434,23 +812,26 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
* @throws CertPathValidatorException if the cert's revocation status * @throws CertPathValidatorException if the cert's revocation status
* cannot be verified successfully with another key * cannot be verified successfully with another key
*/ */
private void verifyWithSeparateSigningKey(X509Certificate currCert, private void verifyWithSeparateSigningKey(X509Certificate cert,
PublicKey prevKey, boolean signFlag, Set<X509Certificate> stackedCerts) PublicKey prevKey,
throws CertPathValidatorException { boolean signFlag,
Set<X509Certificate> stackedCerts)
throws CertPathValidatorException
{
String msg = "revocation status"; String msg = "revocation status";
if (debug != null) { if (debug != null) {
debug.println( debug.println(
"CrlRevocationChecker.verifyWithSeparateSigningKey()" + "RevocationChecker.verifyWithSeparateSigningKey()" +
" ---checking " + msg + "..."); " ---checking " + msg + "...");
} }
// reject circular dependencies - RFC 3280 is not explicit on how // reject circular dependencies - RFC 3280 is not explicit on how
// to handle this, so we feel it is safest to reject them until // to handle this, so we feel it is safest to reject them until
// the issue is resolved in the PKIX WG. // the issue is resolved in the PKIX WG.
if ((stackedCerts != null) && stackedCerts.contains(currCert)) { if ((stackedCerts != null) && stackedCerts.contains(cert)) {
if (debug != null) { if (debug != null) {
debug.println( debug.println(
"CrlRevocationChecker.verifyWithSeparateSigningKey()" + "RevocationChecker.verifyWithSeparateSigningKey()" +
" circular dependency"); " circular dependency");
} }
throw new CertPathValidatorException throw new CertPathValidatorException
...@@ -458,15 +839,15 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -458,15 +839,15 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
-1, BasicReason.UNDETERMINED_REVOCATION_STATUS); -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
} }
// Try to find another key that might be able to sign
// CRLs vouching for this cert.
// If prevKey wasn't trusted, maybe we just didn't have the right // If prevKey wasn't trusted, maybe we just didn't have the right
// path to it. Don't rule that key out. // path to it. Don't rule that key out.
if (!signFlag) { if (!signFlag) {
prevKey = null; buildToNewKey(cert, null, stackedCerts);
} else {
buildToNewKey(cert, prevKey, stackedCerts);
} }
// Try to find another key that might be able to sign
// CRLs vouching for this cert.
buildToNewKey(currCert, prevKey, stackedCerts);
} }
/** /**
...@@ -483,63 +864,51 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -483,63 +864,51 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
* establishment of this path. * establishment of this path.
* @throws CertPathValidatorException on failure * @throws CertPathValidatorException on failure
*/ */
private static final boolean [] CRL_SIGN_USAGE =
{ false, false, false, false, false, false, true };
private void buildToNewKey(X509Certificate currCert, private void buildToNewKey(X509Certificate currCert,
PublicKey prevKey, Set<X509Certificate> stackedCerts) PublicKey prevKey,
throws CertPathValidatorException { Set<X509Certificate> stackedCerts)
throws CertPathValidatorException
{
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" + debug.println("RevocationChecker.buildToNewKey()" +
" starting work"); " starting work");
} }
Set<PublicKey> badKeys = new HashSet<PublicKey>(); Set<PublicKey> badKeys = new HashSet<>();
if (prevKey != null) { if (prevKey != null) {
badKeys.add(prevKey); badKeys.add(prevKey);
} }
X509CertSelector certSel = new RejectKeySelector(badKeys); X509CertSelector certSel = new RejectKeySelector(badKeys);
certSel.setSubject(currCert.getIssuerX500Principal()); certSel.setSubject(currCert.getIssuerX500Principal());
certSel.setKeyUsage(mCrlSignUsage); certSel.setKeyUsage(CRL_SIGN_USAGE);
Set<TrustAnchor> newAnchors = Set<TrustAnchor> newAnchors = anchor == null ?
(mAnchor == null ? mParams.getTrustAnchors() : params.trustAnchors() :
Collections.singleton(mAnchor)); Collections.singleton(anchor);
PKIXBuilderParameters builderParams; PKIXBuilderParameters builderParams;
if (mParams instanceof PKIXBuilderParameters) { try {
builderParams = (PKIXBuilderParameters) mParams.clone(); builderParams = new PKIXBuilderParameters(newAnchors, certSel);
builderParams.setTargetCertConstraints(certSel); } catch (InvalidAlgorithmParameterException iape) {
// Policy qualifiers must be rejected, since we don't have throw new RuntimeException(iape); // should never occur
// any way to convey them back to the application.
builderParams.setPolicyQualifiersRejected(true);
try {
builderParams.setTrustAnchors(newAnchors);
} catch (InvalidAlgorithmParameterException iape) {
throw new RuntimeException(iape); // should never occur
}
} else {
// It's unfortunate that there's no easy way to make a
// PKIXBuilderParameters object from a PKIXParameters
// object. This might miss some things if parameters
// are added in the future or the validatorParams object
// is a custom class derived from PKIXValidatorParameters.
try {
builderParams = new PKIXBuilderParameters(newAnchors, certSel);
} catch (InvalidAlgorithmParameterException iape) {
throw new RuntimeException(iape); // should never occur
}
builderParams.setInitialPolicies(mParams.getInitialPolicies());
builderParams.setCertStores(mStores);
builderParams.setExplicitPolicyRequired
(mParams.isExplicitPolicyRequired());
builderParams.setPolicyMappingInhibited
(mParams.isPolicyMappingInhibited());
builderParams.setAnyPolicyInhibited(mParams.isAnyPolicyInhibited());
// Policy qualifiers must be rejected, since we don't have
// any way to convey them back to the application.
// That's the default, so no need to write code.
builderParams.setDate(mParams.getDate());
builderParams.setCertPathCheckers(mParams.getCertPathCheckers());
builderParams.setSigProvider(mParams.getSigProvider());
} }
builderParams.setInitialPolicies(params.initialPolicies());
builderParams.setCertStores(certStores);
builderParams.setExplicitPolicyRequired
(params.explicitPolicyRequired());
builderParams.setPolicyMappingInhibited
(params.policyMappingInhibited());
builderParams.setAnyPolicyInhibited(params.anyPolicyInhibited());
// Policy qualifiers must be rejected, since we don't have
// any way to convey them back to the application.
// That's the default, so no need to write code.
builderParams.setDate(params.date());
// CertPathCheckers need to be cloned to start from fresh state
builderParams.setCertPathCheckers(
params.getPKIXParameters().getCertPathCheckers());
builderParams.setSigProvider(params.sigProvider());
// Skip revocation during this build to detect circular // Skip revocation during this build to detect circular
// references. But check revocation afterwards, using the // references. But check revocation afterwards, using the
...@@ -554,8 +923,8 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -554,8 +923,8 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
} catch (CertificateException ce) { } catch (CertificateException ce) {
// ignore but log it // ignore but log it
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey: " + debug.println("RevocationChecker.buildToNewKey: " +
"error decoding cert: " + ce); "error decoding cert: " + ce);
} }
} }
AuthorityInfoAccessExtension aiaExt = null; AuthorityInfoAccessExtension aiaExt = null;
...@@ -587,14 +956,14 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -587,14 +956,14 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
while (true) { while (true) {
try { try {
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" + debug.println("RevocationChecker.buildToNewKey()" +
" about to try build ..."); " about to try build ...");
} }
PKIXCertPathBuilderResult cpbr = PKIXCertPathBuilderResult cpbr =
(PKIXCertPathBuilderResult) builder.build(builderParams); (PKIXCertPathBuilderResult)builder.build(builderParams);
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" + debug.println("RevocationChecker.buildToNewKey()" +
" about to check revocation ..."); " about to check revocation ...");
} }
// Now check revocation of all certs in path, assuming that // Now check revocation of all certs in path, assuming that
...@@ -613,14 +982,15 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -613,14 +982,15 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
cpbr.getCertPath().getCertificates(); cpbr.getCertPath().getCertificates();
try { try {
for (int i = cpList.size()-1; i >= 0; i-- ) { for (int i = cpList.size()-1; i >= 0; i-- ) {
X509Certificate cert = (X509Certificate) cpList.get(i); X509Certificate cert = (X509Certificate)cpList.get(i);
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" debug.println("RevocationChecker.buildToNewKey()"
+ " index " + i + " checking " + cert); + " index " + i + " checking "
+ cert);
} }
verifyRevocationStatus(cert, prevKey2, signFlag, true, checkCRLs(cert, prevKey2, signFlag, true,
stackedCerts, newAnchors); stackedCerts, newAnchors);
signFlag = certCanSignCrl(cert); signFlag = certCanSignCrl(cert);
prevKey2 = cert.getPublicKey(); prevKey2 = cert.getPublicKey();
} }
...@@ -631,7 +1001,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -631,7 +1001,7 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
} }
if (debug != null) { if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" + debug.println("RevocationChecker.buildToNewKey()" +
" got key " + cpbr.getPublicKey()); " got key " + cpbr.getPublicKey());
} }
// Now check revocation on the current cert using that key. // Now check revocation on the current cert using that key.
...@@ -639,7 +1009,8 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -639,7 +1009,8 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
// And if we can't find a key, then return false. // And if we can't find a key, then return false.
PublicKey newKey = cpbr.getPublicKey(); PublicKey newKey = cpbr.getPublicKey();
try { try {
verifyRevocationStatus(currCert, newKey, true, false); checkCRLs(currCert, newKey, true, false, null,
params.trustAnchors());
// If that passed, the cert is OK! // If that passed, the cert is OK!
return; return;
} catch (CertPathValidatorException cpve) { } catch (CertPathValidatorException cpve) {
...@@ -689,18 +1060,19 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -689,18 +1060,19 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
* @return <code>true</code> if the <code>Certificate</code> should be * @return <code>true</code> if the <code>Certificate</code> should be
* selected, <code>false</code> otherwise * selected, <code>false</code> otherwise
*/ */
@Override
public boolean match(Certificate cert) { public boolean match(Certificate cert) {
if (!super.match(cert)) if (!super.match(cert))
return(false); return(false);
if (badKeySet.contains(cert.getPublicKey())) { if (badKeySet.contains(cert.getPublicKey())) {
if (debug != null) if (debug != null)
debug.println("RejectCertSelector.match: bad key"); debug.println("RejectKeySelector.match: bad key");
return false; return false;
} }
if (debug != null) if (debug != null)
debug.println("RejectCertSelector.match: returning true"); debug.println("RejectKeySelector.match: returning true");
return true; return true;
} }
...@@ -710,76 +1082,14 @@ class CrlRevocationChecker extends PKIXCertPathChecker { ...@@ -710,76 +1082,14 @@ class CrlRevocationChecker extends PKIXCertPathChecker {
* @return a <code>String</code> describing the contents of the * @return a <code>String</code> describing the contents of the
* <code>CertSelector</code> * <code>CertSelector</code>
*/ */
@Override
public String toString() { public String toString() {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append("RejectCertSelector: [\n"); sb.append("RejectKeySelector: [\n");
sb.append(super.toString()); sb.append(super.toString());
sb.append(badKeySet); sb.append(badKeySet);
sb.append("]"); sb.append("]");
return sb.toString(); return sb.toString();
} }
} }
/**
* Internal method that verifies a set of possible_crls,
* and sees if each is approved, based on the cert.
*
* @param crls a set of possible CRLs to test for acceptability
* @param cert the certificate whose revocation status is being checked
* @param signFlag <code>true</code> if prevKey was trusted to sign CRLs
* @param prevKey the public key of the issuer of cert
* @param reasonsMask the reason code mask
* @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s>
* @return a collection of approved crls (or an empty collection)
*/
private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls,
X509Certificate cert, boolean signFlag, PublicKey prevKey,
boolean[] reasonsMask,
Set<TrustAnchor> trustAnchors) throws CertPathValidatorException {
try {
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
if (debug != null) {
debug.println("CRLRevocationChecker.verifyPossibleCRLs: " +
"Checking CRLDPs for "
+ certImpl.getSubjectX500Principal());
}
CRLDistributionPointsExtension ext =
certImpl.getCRLDistributionPointsExtension();
List<DistributionPoint> points = null;
if (ext == null) {
// assume a DP with reasons and CRLIssuer fields omitted
// and a DP name of the cert issuer.
// TODO add issuerAltName too
X500Name certIssuer = (X500Name)certImpl.getIssuerDN();
DistributionPoint point = new DistributionPoint
(new GeneralNames().add(new GeneralName(certIssuer)),
null, null);
points = Collections.singletonList(point);
} else {
points = ext.get(CRLDistributionPointsExtension.POINTS);
}
Set<X509CRL> results = new HashSet<X509CRL>();
DistributionPointFetcher dpf =
DistributionPointFetcher.getInstance();
for (Iterator<DistributionPoint> t = points.iterator();
t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
DistributionPoint point = t.next();
for (X509CRL crl : crls) {
if (dpf.verifyCRL(certImpl, point, crl, reasonsMask,
signFlag, prevKey, mSigProvider,
trustAnchors, mStores, mParams.getDate())) {
results.add(crl);
}
}
}
return results;
} catch (Exception e) {
if (debug != null) {
debug.println("Exception while verifying CRL: "+e.getMessage());
e.printStackTrace();
}
return Collections.emptySet();
}
}
} }
/* /*
* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -26,10 +26,8 @@ ...@@ -26,10 +26,8 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.io.IOException; import java.io.IOException;
import java.security.AccessController;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.Principal;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.cert.*; import java.security.cert.*;
import java.security.cert.PKIXReason; import java.security.cert.PKIXReason;
...@@ -37,7 +35,6 @@ import java.security.interfaces.DSAPublicKey; ...@@ -37,7 +35,6 @@ import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
...@@ -45,9 +42,8 @@ import java.util.LinkedList; ...@@ -45,9 +42,8 @@ import java.util.LinkedList;
import java.util.Set; import java.util.Set;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.security.action.GetBooleanSecurityPropertyAction; import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.x509.X500Name; import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.PKIXExtensions;
import sun.security.util.Debug; import sun.security.util.Debug;
/** /**
...@@ -78,16 +74,12 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -78,16 +74,12 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/* /*
* private objects shared by methods * private objects shared by methods
*/ */
private PKIXBuilderParameters buildParams; private BuilderParams buildParams;
private CertificateFactory cf; private CertificateFactory cf;
private boolean pathCompleted = false; private boolean pathCompleted = false;
private X500Principal targetSubjectDN;
private PolicyNode policyTreeResult; private PolicyNode policyTreeResult;
private TrustAnchor trustAnchor; private TrustAnchor trustAnchor;
private PublicKey finalPublicKey; private PublicKey finalPublicKey;
private X509CertSelector targetSel;
private List<CertStore> orderedCertStores;
private boolean onlyEECert = false;
/** /**
* Create an instance of <code>SunCertPathBuilder</code>. * Create an instance of <code>SunCertPathBuilder</code>.
...@@ -100,9 +92,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -100,9 +92,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
} catch (CertificateException e) { } catch (CertificateException e) {
throw new CertPathBuilderException(e); throw new CertPathBuilderException(e);
} }
onlyEECert = AccessController.doPrivileged( }
new GetBooleanSecurityPropertyAction
("com.sun.security.onlyCheckRevocationOfEECert")); @Override
public CertPathChecker engineGetRevocationChecker() {
return new RevocationChecker();
} }
/** /**
...@@ -125,6 +119,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -125,6 +119,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* @throws InvalidAlgorithmParameterException if the given parameters are * @throws InvalidAlgorithmParameterException if the given parameters are
* inappropriate for this certification path builder. * inappropriate for this certification path builder.
*/ */
@Override
public CertPathBuilderResult engineBuild(CertPathParameters params) public CertPathBuilderResult engineBuild(CertPathParameters params)
throws CertPathBuilderException, InvalidAlgorithmParameterException { throws CertPathBuilderException, InvalidAlgorithmParameterException {
...@@ -132,66 +127,20 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -132,66 +127,20 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
debug.println("SunCertPathBuilder.engineBuild(" + params + ")"); debug.println("SunCertPathBuilder.engineBuild(" + params + ")");
} }
if (!(params instanceof PKIXBuilderParameters)) { buildParams = PKIX.checkBuilderParams(params);
throw new InvalidAlgorithmParameterException("inappropriate " + return build();
"parameter type, must be an instance of PKIXBuilderParameters"); }
}
boolean buildForward = true;
if (params instanceof SunCertPathBuilderParameters) {
buildForward =
((SunCertPathBuilderParameters)params).getBuildForward();
}
buildParams = (PKIXBuilderParameters)params;
/* Check mandatory parameters */
// Make sure that none of the trust anchors include name constraints
// (not supported).
for (TrustAnchor anchor : buildParams.getTrustAnchors()) {
if (anchor.getNameConstraints() != null) {
throw new InvalidAlgorithmParameterException
("name constraints in trust anchor not supported");
}
}
CertSelector sel = buildParams.getTargetCertConstraints();
if (!(sel instanceof X509CertSelector)) {
throw new InvalidAlgorithmParameterException("the "
+ "targetCertConstraints parameter must be an "
+ "X509CertSelector");
}
targetSel = (X509CertSelector)sel;
targetSubjectDN = targetSel.getSubject();
if (targetSubjectDN == null) {
X509Certificate targetCert = targetSel.getCertificate();
if (targetCert != null) {
targetSubjectDN = targetCert.getSubjectX500Principal();
}
}
// reorder CertStores so that local CertStores are tried first
orderedCertStores =
new ArrayList<CertStore>(buildParams.getCertStores());
Collections.sort(orderedCertStores, new CertStoreComparator());
if (targetSubjectDN == null) {
targetSubjectDN = getTargetSubjectDN(orderedCertStores, targetSel);
}
if (targetSubjectDN == null) {
throw new InvalidAlgorithmParameterException
("Could not determine unique target subject");
}
List<List<Vertex>> adjList = new ArrayList<List<Vertex>>(); private PKIXCertPathBuilderResult build() throws CertPathBuilderException {
CertPathBuilderResult result = List<List<Vertex>> adjList = new ArrayList<>();
buildCertPath(buildForward, false, adjList); PKIXCertPathBuilderResult result = buildCertPath(false, adjList);
if (result == null) { if (result == null) {
if (debug != null) { if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild: 2nd pass"); debug.println("SunCertPathBuilder.engineBuild: 2nd pass");
} }
// try again // try again
adjList.clear(); adjList.clear();
result = buildCertPath(buildForward, true, adjList); result = buildCertPath(true, adjList);
if (result == null) { if (result == null) {
throw new SunCertPathBuilderException("unable to find valid " throw new SunCertPathBuilderException("unable to find valid "
+ "certification path to requested target", + "certification path to requested target",
...@@ -201,24 +150,23 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -201,24 +150,23 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
return result; return result;
} }
private CertPathBuilderResult buildCertPath(boolean buildForward, private PKIXCertPathBuilderResult buildCertPath(boolean searchAllCertStores,
boolean searchAllCertStores, List<List<Vertex>> adjList) List<List<Vertex>> adjList)
throws CertPathBuilderException { throws CertPathBuilderException
{
// Init shared variables and build certification path // Init shared variables and build certification path
pathCompleted = false; pathCompleted = false;
trustAnchor = null; trustAnchor = null;
finalPublicKey = null; finalPublicKey = null;
policyTreeResult = null; policyTreeResult = null;
LinkedList<X509Certificate> certPathList = LinkedList<X509Certificate> certPathList = new LinkedList<>();
new LinkedList<X509Certificate>();
try { try {
if (buildForward) { if (buildParams.buildForward()) {
buildForward(adjList, certPathList, searchAllCertStores); buildForward(adjList, certPathList, searchAllCertStores);
} else { } else {
buildReverse(adjList, certPathList); buildReverse(adjList, certPathList);
} }
} catch (Exception e) { } catch (GeneralSecurityException | IOException e) {
if (debug != null) { if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild() exception in " debug.println("SunCertPathBuilder.engineBuild() exception in "
+ "build"); + "build");
...@@ -242,11 +190,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -242,11 +190,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
Collections.reverse(certPathList); Collections.reverse(certPathList);
return new SunCertPathBuilderResult( return new SunCertPathBuilderResult(
cf.generateCertPath(certPathList), this.trustAnchor, cf.generateCertPath(certPathList), trustAnchor,
policyTreeResult, finalPublicKey, policyTreeResult, finalPublicKey,
new AdjacencyList(adjList)); new AdjacencyList(adjList));
} }
} catch (Exception e) { } catch (CertificateException e) {
if (debug != null) { if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild() exception " debug.println("SunCertPathBuilder.engineBuild() exception "
+ "in wrap-up"); + "in wrap-up");
...@@ -264,12 +212,13 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -264,12 +212,13 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Private build reverse method. * Private build reverse method.
*/ */
private void buildReverse(List<List<Vertex>> adjacencyList, private void buildReverse(List<List<Vertex>> adjacencyList,
LinkedList<X509Certificate> certPathList) throws Exception LinkedList<X509Certificate> certPathList)
throws GeneralSecurityException, IOException
{ {
if (debug != null) { if (debug != null) {
debug.println("SunCertPathBuilder.buildReverse()..."); debug.println("SunCertPathBuilder.buildReverse()...");
debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: " debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: "
+ buildParams.getInitialPolicies()); + buildParams.initialPolicies());
} }
ReverseState currentState = new ReverseState(); ReverseState currentState = new ReverseState();
...@@ -281,11 +230,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -281,11 +230,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Perform a search using each trust anchor, until a valid * Perform a search using each trust anchor, until a valid
* path is found * path is found
*/ */
Iterator<TrustAnchor> iter = buildParams.getTrustAnchors().iterator(); Iterator<TrustAnchor> iter = buildParams.trustAnchors().iterator();
while (iter.hasNext()) { while (iter.hasNext()) {
TrustAnchor anchor = iter.next(); TrustAnchor anchor = iter.next();
/* check if anchor satisfies target constraints */ /* check if anchor satisfies target constraints */
if (anchorIsTarget(anchor, targetSel)) { if (anchorIsTarget(anchor, buildParams.targetCertConstraints())) {
this.trustAnchor = anchor; this.trustAnchor = anchor;
this.pathCompleted = true; this.pathCompleted = true;
this.finalPublicKey = anchor.getTrustedCert().getPublicKey(); this.finalPublicKey = anchor.getTrustedCert().getPublicKey();
...@@ -293,21 +242,15 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -293,21 +242,15 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
} }
/* Initialize current state */ /* Initialize current state */
currentState.initState(buildParams.getMaxPathLength(), currentState.initState(buildParams);
buildParams.isExplicitPolicyRequired(), currentState.updateState(anchor, buildParams);
buildParams.isPolicyMappingInhibited(),
buildParams.isAnyPolicyInhibited(),
buildParams.getCertPathCheckers());
currentState.updateState(anchor);
// init the crl checker
currentState.crlChecker =
new CrlRevocationChecker(null, buildParams, null, onlyEECert);
currentState.algorithmChecker = new AlgorithmChecker(anchor); currentState.algorithmChecker = new AlgorithmChecker(anchor);
try { try {
depthFirstSearchReverse(null, currentState, depthFirstSearchReverse(null, currentState,
new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList, new ReverseBuilder(buildParams),
certPathList); adjacencyList, certPathList);
} catch (Exception e) { } catch (GeneralSecurityException | IOException e) {
// continue on error if more anchors to try // continue on error if more anchors to try
if (iter.hasNext()) if (iter.hasNext())
continue; continue;
...@@ -331,7 +274,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -331,7 +274,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Private build forward method. * Private build forward method.
*/ */
private void buildForward(List<List<Vertex>> adjacencyList, private void buildForward(List<List<Vertex>> adjacencyList,
LinkedList<X509Certificate> certPathList, boolean searchAllCertStores) LinkedList<X509Certificate> certPathList,
boolean searchAllCertStores)
throws GeneralSecurityException, IOException throws GeneralSecurityException, IOException
{ {
if (debug != null) { if (debug != null) {
...@@ -340,20 +284,16 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -340,20 +284,16 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/* Initialize current state */ /* Initialize current state */
ForwardState currentState = new ForwardState(); ForwardState currentState = new ForwardState();
currentState.initState(buildParams.getCertPathCheckers()); currentState.initState(buildParams.certPathCheckers());
/* Initialize adjacency list */ /* Initialize adjacency list */
adjacencyList.clear(); adjacencyList.clear();
adjacencyList.add(new LinkedList<Vertex>()); adjacencyList.add(new LinkedList<Vertex>());
// init the crl checker depthFirstSearchForward(buildParams.targetSubject(), currentState,
currentState.crlChecker new ForwardBuilder(buildParams,
= new CrlRevocationChecker(null, buildParams, null, onlyEECert); searchAllCertStores),
adjacencyList, certPathList);
depthFirstSearchForward(targetSubjectDN, currentState,
new ForwardBuilder
(buildParams, targetSubjectDN, searchAllCertStores, onlyEECert),
adjacencyList, certPathList);
} }
/* /*
...@@ -371,27 +311,28 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -371,27 +311,28 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* @param dN the distinguished name being currently searched for certs * @param dN the distinguished name being currently searched for certs
* @param currentState the current PKIX validation state * @param currentState the current PKIX validation state
*/ */
void depthFirstSearchForward(X500Principal dN, ForwardState currentState, private void depthFirstSearchForward(X500Principal dN,
ForwardBuilder builder, List<List<Vertex>> adjList, ForwardState currentState,
LinkedList<X509Certificate> certPathList) ForwardBuilder builder,
List<List<Vertex>> adjList,
LinkedList<X509Certificate> cpList)
throws GeneralSecurityException, IOException throws GeneralSecurityException, IOException
{ {
//XXX This method should probably catch & handle exceptions
if (debug != null) { if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward(" + dN debug.println("SunCertPathBuilder.depthFirstSearchForward(" + dN
+ ", " + currentState.toString() + ")"); + ", " + currentState.toString() + ")");
} }
/* /*
* Find all the certificates issued to dN which * Find all the certificates issued to dN which
* satisfy the PKIX certification path constraints. * satisfy the PKIX certification path constraints.
*/ */
List<Vertex> vertices = addVertices Collection<X509Certificate> certs =
(builder.getMatchingCerts(currentState, orderedCertStores), adjList); builder.getMatchingCerts(currentState, buildParams.certStores());
List<Vertex> vertices = addVertices(certs, adjList);
if (debug != null) { if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward(): " debug.println("SunCertPathBuilder.depthFirstSearchForward(): "
+ "certs.size=" + vertices.size()); + "certs.size=" + vertices.size());
} }
/* /*
...@@ -411,14 +352,14 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -411,14 +352,14 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* the next matching cert is tried. * the next matching cert is tried.
*/ */
ForwardState nextState = (ForwardState) currentState.clone(); ForwardState nextState = (ForwardState) currentState.clone();
X509Certificate cert = (X509Certificate) vertex.getCertificate(); X509Certificate cert = vertex.getCertificate();
try { try {
builder.verifyCert(cert, nextState, certPathList); builder.verifyCert(cert, nextState, cpList);
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
if (debug != null) { if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward()" debug.println("SunCertPathBuilder.depthFirstSearchForward()"
+ ": validation failed: " + gse); + ": validation failed: " + gse);
gse.printStackTrace(); gse.printStackTrace();
} }
vertex.setThrowable(gse); vertex.setThrowable(gse);
...@@ -436,51 +377,44 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -436,51 +377,44 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
*/ */
if (builder.isPathCompleted(cert)) { if (builder.isPathCompleted(cert)) {
BasicChecker basicChecker = null;
if (debug != null) if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward()" debug.println("SunCertPathBuilder.depthFirstSearchForward()"
+ ": commencing final verification"); + ": commencing final verification");
ArrayList<X509Certificate> appendedCerts = List<X509Certificate> appendedCerts = new ArrayList<>(cpList);
new ArrayList<X509Certificate>(certPathList);
/* /*
* if the trust anchor selected is specified as a trusted * if the trust anchor selected is specified as a trusted
* public key rather than a trusted cert, then verify this * public key rather than a trusted cert, then verify this
* cert (which is signed by the trusted public key), but * cert (which is signed by the trusted public key), but
* don't add it yet to the certPathList * don't add it yet to the cpList
*/ */
if (builder.trustAnchor.getTrustedCert() == null) { if (builder.trustAnchor.getTrustedCert() == null) {
appendedCerts.add(0, cert); appendedCerts.add(0, cert);
} }
HashSet<String> initExpPolSet = new HashSet<String>(1); Set<String> initExpPolSet =
initExpPolSet.add(PolicyChecker.ANY_POLICY); Collections.singleton(PolicyChecker.ANY_POLICY);
PolicyNodeImpl rootNode = new PolicyNodeImpl(null, PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false); PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
List<PKIXCertPathChecker> checkers = new ArrayList<>();
PolicyChecker policyChecker PolicyChecker policyChecker
= new PolicyChecker(buildParams.getInitialPolicies(), = new PolicyChecker(buildParams.initialPolicies(),
appendedCerts.size(), appendedCerts.size(),
buildParams.isExplicitPolicyRequired(), buildParams.explicitPolicyRequired(),
buildParams.isPolicyMappingInhibited(), buildParams.policyMappingInhibited(),
buildParams.isAnyPolicyInhibited(), buildParams.anyPolicyInhibited(),
buildParams.getPolicyQualifiersRejected(), buildParams.policyQualifiersRejected(),
rootNode); rootNode);
List<PKIXCertPathChecker> userCheckers = new checkers.add(policyChecker);
ArrayList<PKIXCertPathChecker>
(buildParams.getCertPathCheckers());
int mustCheck = 0;
userCheckers.add(mustCheck, policyChecker);
mustCheck++;
// add the algorithm checker // add the algorithm checker
userCheckers.add(mustCheck, checkers.add(new AlgorithmChecker(builder.trustAnchor));
new AlgorithmChecker(builder.trustAnchor));
mustCheck++;
BasicChecker basicChecker = null;
if (nextState.keyParamsNeeded()) { if (nextState.keyParamsNeeded()) {
PublicKey rootKey = cert.getPublicKey(); PublicKey rootKey = cert.getPublicKey();
if (builder.trustAnchor.getTrustedCert() == null) { if (builder.trustAnchor.getTrustedCert() == null) {
...@@ -495,24 +429,38 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -495,24 +429,38 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
(cert.getSubjectX500Principal(), rootKey, null); (cert.getSubjectX500Principal(), rootKey, null);
// add the basic checker // add the basic checker
basicChecker = new BasicChecker(anchor, basicChecker = new BasicChecker(anchor, buildParams.date(),
builder.date, buildParams.sigProvider(),
buildParams.getSigProvider(), true);
true); checkers.add(basicChecker);
userCheckers.add(mustCheck, basicChecker); }
mustCheck++;
buildParams.setCertPath(cf.generateCertPath(appendedCerts));
// add the crl revocation checker
if (buildParams.isRevocationEnabled()) { boolean revCheckerAdded = false;
userCheckers.add(mustCheck, new CrlRevocationChecker List<PKIXCertPathChecker> ckrs = buildParams.certPathCheckers();
(anchor, buildParams, null, onlyEECert)); for (PKIXCertPathChecker ckr : ckrs) {
mustCheck++; if (ckr instanceof PKIXRevocationChecker) {
revCheckerAdded = true;
// if it's our own, initialize it
if (ckr instanceof RevocationChecker)
((RevocationChecker)ckr).init(builder.trustAnchor,
buildParams);
} }
} }
// Why we don't need BasicChecker and CrlRevocationChecker // only add a RevocationChecker if revocation is enabled and
// a PKIXRevocationChecker has not already been added
if (buildParams.revocationEnabled() && !revCheckerAdded) {
checkers.add(new RevocationChecker(builder.trustAnchor,
buildParams));
}
checkers.addAll(ckrs);
// Why we don't need BasicChecker and RevocationChecker
// if nextState.keyParamsNeeded() is false? // if nextState.keyParamsNeeded() is false?
for (int i=0; i<appendedCerts.size(); i++) { for (int i = 0; i < appendedCerts.size(); i++) {
X509Certificate currCert = appendedCerts.get(i); X509Certificate currCert = appendedCerts.get(i);
if (debug != null) if (debug != null)
debug.println("current subject = " debug.println("current subject = "
...@@ -523,18 +471,15 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -523,18 +471,15 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
unresCritExts = Collections.<String>emptySet(); unresCritExts = Collections.<String>emptySet();
} }
for (int j=0; j<userCheckers.size(); j++) { for (PKIXCertPathChecker currChecker : checkers) {
PKIXCertPathChecker currChecker = userCheckers.get(j); if (!currChecker.isForwardCheckingSupported()) {
if (j < mustCheck ||
!currChecker.isForwardCheckingSupported()) {
if (i == 0) { if (i == 0) {
currChecker.init(false); currChecker.init(false);
// The user specified // The user specified
// AlgorithmChecker may not be // AlgorithmChecker may not be
// able to set the trust anchor until now. // able to set the trust anchor until now.
if (j >= mustCheck && if (currChecker instanceof AlgorithmChecker) {
currChecker instanceof AlgorithmChecker) {
((AlgorithmChecker)currChecker). ((AlgorithmChecker)currChecker).
trySetTrustAnchor(builder.trustAnchor); trySetTrustAnchor(builder.trustAnchor);
} }
...@@ -560,7 +505,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -560,7 +505,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* are capable of processing. * are capable of processing.
*/ */
for (PKIXCertPathChecker checker : for (PKIXCertPathChecker checker :
buildParams.getCertPathCheckers()) buildParams.certPathCheckers())
{ {
if (checker.isForwardCheckingSupported()) { if (checker.isForwardCheckingSupported()) {
Set<String> suppExts = Set<String> suppExts =
...@@ -572,24 +517,16 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -572,24 +517,16 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
} }
if (!unresCritExts.isEmpty()) { if (!unresCritExts.isEmpty()) {
unresCritExts.remove unresCritExts.remove(BasicConstraints_Id.toString());
(PKIXExtensions.BasicConstraints_Id.toString()); unresCritExts.remove(NameConstraints_Id.toString());
unresCritExts.remove unresCritExts.remove(CertificatePolicies_Id.toString());
(PKIXExtensions.NameConstraints_Id.toString()); unresCritExts.remove(PolicyMappings_Id.toString());
unresCritExts.remove unresCritExts.remove(PolicyConstraints_Id.toString());
(PKIXExtensions.CertificatePolicies_Id.toString()); unresCritExts.remove(InhibitAnyPolicy_Id.toString());
unresCritExts.remove unresCritExts.remove(
(PKIXExtensions.PolicyMappings_Id.toString());
unresCritExts.remove
(PKIXExtensions.PolicyConstraints_Id.toString());
unresCritExts.remove
(PKIXExtensions.InhibitAnyPolicy_Id.toString());
unresCritExts.remove(PKIXExtensions.
SubjectAlternativeName_Id.toString()); SubjectAlternativeName_Id.toString());
unresCritExts.remove unresCritExts.remove(KeyUsage_Id.toString());
(PKIXExtensions.KeyUsage_Id.toString()); unresCritExts.remove(ExtendedKeyUsage_Id.toString());
unresCritExts.remove
(PKIXExtensions.ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty()) { if (!unresCritExts.isEmpty()) {
throw new CertPathValidatorException throw new CertPathValidatorException
...@@ -606,10 +543,10 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -606,10 +543,10 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/* /*
* if the user specified a trusted public key rather than * if the user specified a trusted public key rather than
* trusted certs, then add this cert (which is signed by * trusted certs, then add this cert (which is signed by
* the trusted public key) to the certPathList * the trusted public key) to the cpList
*/ */
if (builder.trustAnchor.getTrustedCert() == null) if (builder.trustAnchor.getTrustedCert() == null)
builder.addCertToPath(cert, certPathList); builder.addCertToPath(cert, cpList);
// Save the trust anchor // Save the trust anchor
this.trustAnchor = builder.trustAnchor; this.trustAnchor = builder.trustAnchor;
...@@ -620,10 +557,10 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -620,10 +557,10 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
finalPublicKey = basicChecker.getPublicKey(); finalPublicKey = basicChecker.getPublicKey();
} else { } else {
Certificate finalCert; Certificate finalCert;
if (certPathList.size() == 0) { if (cpList.isEmpty()) {
finalCert = builder.trustAnchor.getTrustedCert(); finalCert = builder.trustAnchor.getTrustedCert();
} else { } else {
finalCert = certPathList.get(certPathList.size()-1); finalCert = cpList.getLast();
} }
finalPublicKey = finalCert.getPublicKey(); finalPublicKey = finalCert.getPublicKey();
} }
...@@ -631,7 +568,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -631,7 +568,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
policyTreeResult = policyChecker.getPolicyTree(); policyTreeResult = policyChecker.getPolicyTree();
return; return;
} else { } else {
builder.addCertToPath(cert, certPathList); builder.addCertToPath(cert, cpList);
} }
/* Update the PKIX state */ /* Update the PKIX state */
...@@ -645,8 +582,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -645,8 +582,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
vertex.setIndex(adjList.size() - 1); vertex.setIndex(adjList.size() - 1);
/* recursively search for matching certs at next dN */ /* recursively search for matching certs at next dN */
depthFirstSearchForward(cert.getIssuerX500Principal(), nextState, builder, depthFirstSearchForward(cert.getIssuerX500Principal(), nextState,
adjList, certPathList); builder, adjList, cpList);
/* /*
* If path has been completed, return ASAP! * If path has been completed, return ASAP!
...@@ -662,8 +599,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -662,8 +599,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
*/ */
if (debug != null) if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward()" debug.println("SunCertPathBuilder.depthFirstSearchForward()"
+ ": backtracking"); + ": backtracking");
builder.removeFinalCertFromPath(certPathList); builder.removeFinalCertFromPath(cpList);
} }
} }
} }
...@@ -683,9 +620,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -683,9 +620,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* @param dN the distinguished name being currently searched for certs * @param dN the distinguished name being currently searched for certs
* @param currentState the current PKIX validation state * @param currentState the current PKIX validation state
*/ */
void depthFirstSearchReverse(X500Principal dN, ReverseState currentState, private void depthFirstSearchReverse(X500Principal dN,
ReverseBuilder builder, List<List<Vertex>> adjList, ReverseState currentState,
LinkedList<X509Certificate> certPathList) ReverseBuilder builder,
List<List<Vertex>> adjList,
LinkedList<X509Certificate> cpList)
throws GeneralSecurityException, IOException throws GeneralSecurityException, IOException
{ {
if (debug != null) if (debug != null)
...@@ -696,8 +635,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -696,8 +635,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Find all the certificates issued by dN which * Find all the certificates issued by dN which
* satisfy the PKIX certification path constraints. * satisfy the PKIX certification path constraints.
*/ */
List<Vertex> vertices = addVertices Collection<X509Certificate> certs =
(builder.getMatchingCerts(currentState, orderedCertStores), adjList); builder.getMatchingCerts(currentState, buildParams.certStores());
List<Vertex> vertices = addVertices(certs, adjList);
if (debug != null) if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchReverse(): " debug.println("SunCertPathBuilder.depthFirstSearchReverse(): "
+ "certs.size=" + vertices.size()); + "certs.size=" + vertices.size());
...@@ -717,9 +657,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -717,9 +657,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* the next matching cert is tried. * the next matching cert is tried.
*/ */
ReverseState nextState = (ReverseState) currentState.clone(); ReverseState nextState = (ReverseState) currentState.clone();
X509Certificate cert = (X509Certificate) vertex.getCertificate(); X509Certificate cert = vertex.getCertificate();
try { try {
builder.verifyCert(cert, nextState, certPathList); builder.verifyCert(cert, nextState, cpList);
} catch (GeneralSecurityException gse) { } catch (GeneralSecurityException gse) {
if (debug != null) if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchReverse()" debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
...@@ -733,7 +673,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -733,7 +673,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* self-signed cert) and update state * self-signed cert) and update state
*/ */
if (!currentState.isInitial()) if (!currentState.isInitial())
builder.addCertToPath(cert, certPathList); builder.addCertToPath(cert, cpList);
// save trust anchor // save trust anchor
this.trustAnchor = currentState.trustAnchor; this.trustAnchor = currentState.trustAnchor;
...@@ -782,7 +722,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -782,7 +722,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/* recursively search for matching certs at next dN */ /* recursively search for matching certs at next dN */
depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState, depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState,
builder, adjList, certPathList); builder, adjList, cpList);
/* /*
* If path has been completed, return ASAP! * If path has been completed, return ASAP!
...@@ -800,7 +740,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -800,7 +740,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
debug.println("SunCertPathBuilder.depthFirstSearchReverse()" debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
+ ": backtracking"); + ": backtracking");
if (!currentState.isInitial()) if (!currentState.isInitial())
builder.removeFinalCertFromPath(certPathList); builder.removeFinalCertFromPath(cpList);
} }
} }
if (debug != null) if (debug != null)
...@@ -812,13 +752,14 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -812,13 +752,14 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Adds a collection of matching certificates to the * Adds a collection of matching certificates to the
* adjacency list. * adjacency list.
*/ */
private List<Vertex> addVertices(Collection<X509Certificate> certs, private static List<Vertex> addVertices(Collection<X509Certificate> certs,
List<List<Vertex>> adjList) { List<List<Vertex>> adjList)
{
List<Vertex> l = adjList.get(adjList.size() - 1); List<Vertex> l = adjList.get(adjList.size() - 1);
for (X509Certificate cert : certs) { for (X509Certificate cert : certs) {
Vertex v = new Vertex(cert); Vertex v = new Vertex(cert);
l.add(v); l.add(v);
} }
return l; return l;
...@@ -828,53 +769,13 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi { ...@@ -828,53 +769,13 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Returns true if trust anchor certificate matches specified * Returns true if trust anchor certificate matches specified
* certificate constraints. * certificate constraints.
*/ */
private boolean anchorIsTarget(TrustAnchor anchor, X509CertSelector sel) { private static boolean anchorIsTarget(TrustAnchor anchor,
CertSelector sel)
{
X509Certificate anchorCert = anchor.getTrustedCert(); X509Certificate anchorCert = anchor.getTrustedCert();
if (anchorCert != null) { if (anchorCert != null) {
return sel.match(anchorCert); return sel.match(anchorCert);
} }
return false; return false;
} }
/**
* Comparator that orders CertStores so that local CertStores come before
* remote CertStores.
*/
private static class CertStoreComparator implements Comparator<CertStore> {
public int compare(CertStore store1, CertStore store2) {
if (Builder.isLocalCertStore(store1)) {
return -1;
} else {
return 1;
}
}
}
/**
* Returns the target subject DN from the first X509Certificate that
* is fetched that matches the specified X509CertSelector.
*/
private X500Principal getTargetSubjectDN(List<CertStore> stores,
X509CertSelector targetSel) {
for (CertStore store : stores) {
try {
Collection<? extends Certificate> targetCerts =
(Collection<? extends Certificate>)
store.getCertificates(targetSel);
if (!targetCerts.isEmpty()) {
X509Certificate targetCert =
(X509Certificate)targetCerts.iterator().next();
return targetCert.getSubjectX500Principal();
}
} catch (CertStoreException e) {
// ignore but log it
if (debug != null) {
debug.println("SunCertPathBuilder.getTargetSubjectDN: " +
"non-fatal exception retrieving certs: " + e);
e.printStackTrace();
}
}
}
return null;
}
} }
/* /*
* Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,12 +25,11 @@ ...@@ -25,12 +25,11 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import java.util.Set;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.KeyStoreException; import java.security.KeyStoreException;
import java.security.cert.*; import java.security.cert.*;
import java.util.Set;
/** /**
* This class specifies the set of parameters used as input for the Sun * This class specifies the set of parameters used as input for the Sun
...@@ -120,8 +119,9 @@ public class SunCertPathBuilderParameters extends PKIXBuilderParameters { ...@@ -120,8 +119,9 @@ public class SunCertPathBuilderParameters extends PKIXBuilderParameters {
* *
* @return a formatted string describing the parameters. * @return a formatted string describing the parameters.
*/ */
@Override
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuilder sb = new StringBuilder();
sb.append("[\n"); sb.append("[\n");
sb.append(super.toString()); sb.append(super.toString());
sb.append(" Build Forward Flag: " + String.valueOf(buildForward) + "\n"); sb.append(" Build Forward Flag: " + String.valueOf(buildForward) + "\n");
......
/* /*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -213,6 +213,7 @@ class URICertStore extends CertStoreSpi { ...@@ -213,6 +213,7 @@ class URICertStore extends CertStoreSpi {
* match the specified selector * match the specified selector
* @throws CertStoreException if an exception occurs * @throws CertStoreException if an exception occurs
*/ */
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public synchronized Collection<X509Certificate> engineGetCertificates public synchronized Collection<X509Certificate> engineGetCertificates
(CertSelector selector) throws CertStoreException { (CertSelector selector) throws CertStoreException {
...@@ -322,6 +323,7 @@ class URICertStore extends CertStoreSpi { ...@@ -322,6 +323,7 @@ class URICertStore extends CertStoreSpi {
* match the specified selector * match the specified selector
* @throws CertStoreException if an exception occurs * @throws CertStoreException if an exception occurs
*/ */
@Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector) public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException { throws CertStoreException {
...@@ -418,14 +420,14 @@ class URICertStore extends CertStoreSpi { ...@@ -418,14 +420,14 @@ class URICertStore extends CertStoreSpi {
URICertStoreParameters(URI uri) { URICertStoreParameters(URI uri) {
this.uri = uri; this.uri = uri;
} }
public boolean equals(Object obj) { @Override public boolean equals(Object obj) {
if (!(obj instanceof URICertStoreParameters)) { if (!(obj instanceof URICertStoreParameters)) {
return false; return false;
} }
URICertStoreParameters params = (URICertStoreParameters) obj; URICertStoreParameters params = (URICertStoreParameters) obj;
return uri.equals(params.uri); return uri.equals(params.uri);
} }
public int hashCode() { @Override public int hashCode() {
if (hashCode == 0) { if (hashCode == 0) {
int result = 17; int result = 17;
result = 37*result + uri.hashCode(); result = 37*result + uri.hashCode();
...@@ -433,7 +435,7 @@ class URICertStore extends CertStoreSpi { ...@@ -433,7 +435,7 @@ class URICertStore extends CertStoreSpi {
} }
return hashCode; return hashCode;
} }
public Object clone() { @Override public Object clone() {
try { try {
return super.clone(); return super.clone();
} catch (CloneNotSupportedException e) { } catch (CloneNotSupportedException e) {
......
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,12 +25,11 @@ ...@@ -25,12 +25,11 @@
package sun.security.provider.certpath; package sun.security.provider.certpath;
import sun.security.util.Debug; import java.io.IOException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import sun.security.util.Debug;
import sun.security.x509.AuthorityKeyIdentifierExtension; import sun.security.x509.AuthorityKeyIdentifierExtension;
import sun.security.x509.KeyIdentifier; import sun.security.x509.KeyIdentifier;
import sun.security.x509.SubjectKeyIdentifierExtension; import sun.security.x509.SubjectKeyIdentifierExtension;
...@@ -50,17 +49,17 @@ import sun.security.x509.X509CertImpl; ...@@ -50,17 +49,17 @@ import sun.security.x509.X509CertImpl;
public class Vertex { public class Vertex {
private static final Debug debug = Debug.getInstance("certpath"); private static final Debug debug = Debug.getInstance("certpath");
private Certificate cert; private X509Certificate cert;
private int index; private int index;
private Throwable throwable; private Throwable throwable;
/** /**
* Constructor; creates vertex with index of -1 * Constructor; creates vertex with index of -1
* Use setIndex method to set another index. * Use setIndex method to set another index.
* *
* @param cert Certificate associated with vertex * @param cert X509Certificate associated with vertex
*/ */
Vertex(Certificate cert) { Vertex(X509Certificate cert) {
this.cert = cert; this.cert = cert;
this.index = -1; this.index = -1;
} }
...@@ -68,9 +67,9 @@ public class Vertex { ...@@ -68,9 +67,9 @@ public class Vertex {
/** /**
* return the certificate for this vertex * return the certificate for this vertex
* *
* @returns Certificate * @returns X509Certificate
*/ */
public Certificate getCertificate() { public X509Certificate getCertificate() {
return cert; return cert;
} }
...@@ -121,6 +120,7 @@ public class Vertex { ...@@ -121,6 +120,7 @@ public class Vertex {
* *
* @returns String representation of vertex * @returns String representation of vertex
*/ */
@Override
public String toString() { public String toString() {
return certToString() + throwableToString() + indexToString(); return certToString() + throwableToString() + indexToString();
} }
...@@ -132,70 +132,65 @@ public class Vertex { ...@@ -132,70 +132,65 @@ public class Vertex {
* @returns String representation of certificate info * @returns String representation of certificate info
*/ */
public String certToString() { public String certToString() {
String out = ""; StringBuilder sb = new StringBuilder();
if (cert == null || ! (cert instanceof X509Certificate))
return "Cert: Not an X509Certificate\n";
X509CertImpl x509Cert = null; X509CertImpl x509Cert = null;
try { try {
x509Cert = X509CertImpl.toImpl((X509Certificate)cert); x509Cert = X509CertImpl.toImpl(cert);
} catch (CertificateException ce) { } catch (CertificateException ce) {
if (debug != null) { if (debug != null) {
debug.println("Vertex.certToString() unexpected exception"); debug.println("Vertex.certToString() unexpected exception");
ce.printStackTrace(); ce.printStackTrace();
} }
return out; return sb.toString();
} }
out = "Issuer: " + x509Cert.getIssuerX500Principal() + "\n"; sb.append("Issuer: ").append
out = out + "Subject: " + x509Cert.getSubjectX500Principal() + "\n"; (x509Cert.getIssuerX500Principal()).append("\n");
out = out + "SerialNum: " + (x509Cert.getSerialNumber()).toString(16) + "\n"; sb.append("Subject: ").append
out = out + "Expires: " + x509Cert.getNotAfter().toString() + "\n"; (x509Cert.getSubjectX500Principal()).append("\n");
sb.append("SerialNum: ").append
(x509Cert.getSerialNumber().toString(16)).append("\n");
sb.append("Expires: ").append
(x509Cert.getNotAfter().toString()).append("\n");
boolean[] iUID = x509Cert.getIssuerUniqueID(); boolean[] iUID = x509Cert.getIssuerUniqueID();
if (iUID != null) { if (iUID != null) {
out = out + "IssuerUID: "; sb.append("IssuerUID: ");
for (int i=0; i < iUID.length; i++) { for (boolean b : iUID) {
out = out + (iUID[i]?1:0); sb.append(b ? 1 : 0);
} }
out = out + "\n"; sb.append("\n");
} }
boolean[] sUID = x509Cert.getSubjectUniqueID(); boolean[] sUID = x509Cert.getSubjectUniqueID();
if (sUID != null) { if (sUID != null) {
out = out + "SubjectUID: "; sb.append("SubjectUID: ");
for (int i=0; i< sUID.length; i++) { for (boolean b : sUID) {
out = out + (sUID[i]?1:0); sb.append(b ? 1 : 0);
} }
out = out + "\n"; sb.append("\n");
} }
SubjectKeyIdentifierExtension sKeyID = null;
try { try {
sKeyID = x509Cert.getSubjectKeyIdentifierExtension(); SubjectKeyIdentifierExtension sKeyID =
x509Cert.getSubjectKeyIdentifierExtension();
if (sKeyID != null) { if (sKeyID != null) {
KeyIdentifier keyID = sKeyID.get( KeyIdentifier keyID = sKeyID.get(
SubjectKeyIdentifierExtension.KEY_ID); SubjectKeyIdentifierExtension.KEY_ID);
out = out + "SubjKeyID: " + keyID.toString(); sb.append("SubjKeyID: ").append(keyID.toString());
}
} catch (Exception e) {
if (debug != null) {
debug.println("Vertex.certToString() unexpected exception");
e.printStackTrace();
} }
} AuthorityKeyIdentifierExtension aKeyID =
AuthorityKeyIdentifierExtension aKeyID = null; x509Cert.getAuthorityKeyIdentifierExtension();
try {
aKeyID = x509Cert.getAuthorityKeyIdentifierExtension();
if (aKeyID != null) { if (aKeyID != null) {
KeyIdentifier keyID = (KeyIdentifier)aKeyID.get( KeyIdentifier keyID = (KeyIdentifier)aKeyID.get(
AuthorityKeyIdentifierExtension.KEY_ID); AuthorityKeyIdentifierExtension.KEY_ID);
out = out + "AuthKeyID: " + keyID.toString(); sb.append("AuthKeyID: ").append(keyID.toString());
} }
} catch (Exception e) { } catch (IOException e) {
if (debug != null) { if (debug != null) {
debug.println("Vertex.certToString() 2 unexpected exception"); debug.println("Vertex.certToString() unexpected exception");
e.printStackTrace(); e.printStackTrace();
} }
} }
return out; return sb.toString();
} }
/** /**
...@@ -205,13 +200,13 @@ public class Vertex { ...@@ -205,13 +200,13 @@ public class Vertex {
* @returns String form of exception (or "none") * @returns String form of exception (or "none")
*/ */
public String throwableToString() { public String throwableToString() {
String out = "Exception: "; StringBuilder sb = new StringBuilder("Exception: ");
if (throwable != null) if (throwable != null)
out = out + throwable.toString(); sb.append(throwable.toString());
else else
out = out + "null"; sb.append("null");
out = out + "\n"; sb.append("\n");
return out; return sb.toString();
} }
/** /**
...@@ -222,10 +217,10 @@ public class Vertex { ...@@ -222,10 +217,10 @@ public class Vertex {
* @returns String form of index as "Last cert? [Yes/No] * @returns String form of index as "Last cert? [Yes/No]
*/ */
public String moreToString() { public String moreToString() {
String out = "Last cert? "; StringBuilder sb = new StringBuilder("Last cert? ");
out = out + ((index == -1)?"Yes":"No"); sb.append((index == -1) ? "Yes" : "No");
out = out + "\n"; sb.append("\n");
return out; return sb.toString();
} }
/** /**
...@@ -235,7 +230,6 @@ public class Vertex { ...@@ -235,7 +230,6 @@ public class Vertex {
* @returns String form of index as "Index: [numeric index]" * @returns String form of index as "Index: [numeric index]"
*/ */
public String indexToString() { public String indexToString() {
String out = "Index: " + index + "\n"; return "Index: " + index + "\n";
return out;
} }
} }
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -33,9 +33,10 @@ import java.security.cert.CertificateEncodingException; ...@@ -33,9 +33,10 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory; import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate; import java.security.cert.X509Certificate;
import java.util.*; import java.util.*;
import java.security.cert.CertPath;
import sun.security.pkcs.ContentInfo; import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7; import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo; import sun.security.pkcs.SignerInfo;
...@@ -44,7 +45,6 @@ import sun.security.util.DerValue; ...@@ -44,7 +45,6 @@ import sun.security.util.DerValue;
import sun.security.util.DerOutputStream; import sun.security.util.DerOutputStream;
import sun.security.util.DerInputStream; import sun.security.util.DerInputStream;
/** /**
* A {@link java.security.cert.CertPath CertPath} (certification path) * A {@link java.security.cert.CertPath CertPath} (certification path)
* consisting exclusively of * consisting exclusively of
...@@ -83,7 +83,7 @@ public class X509CertPath extends CertPath { ...@@ -83,7 +83,7 @@ public class X509CertPath extends CertPath {
private static final Collection<String> encodingList; private static final Collection<String> encodingList;
static { static {
List<String> list = new ArrayList<String>(2); List<String> list = new ArrayList<>(2);
list.add(PKIPATH_ENCODING); list.add(PKIPATH_ENCODING);
list.add(PKCS7_ENCODING); list.add(PKCS7_ENCODING);
encodingList = Collections.unmodifiableCollection(list); encodingList = Collections.unmodifiableCollection(list);
...@@ -272,6 +272,7 @@ public class X509CertPath extends CertPath { ...@@ -272,6 +272,7 @@ public class X509CertPath extends CertPath {
* @return the encoded bytes * @return the encoded bytes
* @exception CertificateEncodingException if an encoding error occurs * @exception CertificateEncodingException if an encoding error occurs
*/ */
@Override
public byte[] getEncoded() throws CertificateEncodingException { public byte[] getEncoded() throws CertificateEncodingException {
// @@@ Should cache the encoded form // @@@ Should cache the encoded form
return encodePKIPATH(); return encodePKIPATH();
...@@ -342,6 +343,7 @@ public class X509CertPath extends CertPath { ...@@ -342,6 +343,7 @@ public class X509CertPath extends CertPath {
* @exception CertificateEncodingException if an encoding error occurs or * @exception CertificateEncodingException if an encoding error occurs or
* the encoding requested is not supported * the encoding requested is not supported
*/ */
@Override
public byte[] getEncoded(String encoding) public byte[] getEncoded(String encoding)
throws CertificateEncodingException { throws CertificateEncodingException {
switch (encoding) { switch (encoding) {
...@@ -376,6 +378,7 @@ public class X509CertPath extends CertPath { ...@@ -376,6 +378,7 @@ public class X509CertPath extends CertPath {
* @return an <code>Iterator</code> over the names of the supported * @return an <code>Iterator</code> over the names of the supported
* encodings (as Strings) * encodings (as Strings)
*/ */
@Override
public Iterator<String> getEncodings() { public Iterator<String> getEncodings() {
return getEncodingsStatic(); return getEncodingsStatic();
} }
...@@ -387,6 +390,7 @@ public class X509CertPath extends CertPath { ...@@ -387,6 +390,7 @@ public class X509CertPath extends CertPath {
* @return an immutable <code>List</code> of <code>X509Certificate</code>s * @return an immutable <code>List</code> of <code>X509Certificate</code>s
* (may be empty, but not null) * (may be empty, but not null)
*/ */
@Override
public List<X509Certificate> getCertificates() { public List<X509Certificate> getCertificates() {
return certs; return certs;
} }
......
/* /*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -207,13 +207,14 @@ public class X509CertificatePair { ...@@ -207,13 +207,14 @@ public class X509CertificatePair {
* *
* @return A String describing the contents of the pair. * @return A String describing the contents of the pair.
*/ */
@Override
public String toString() { public String toString() {
StringBuffer sb = new StringBuffer(); StringBuilder sb = new StringBuilder();
sb.append("X.509 Certificate Pair: [\n"); sb.append("X.509 Certificate Pair: [\n");
if (forward != null) if (forward != null)
sb.append(" Forward: " + forward + "\n"); sb.append(" Forward: ").append(forward).append("\n");
if (reverse != null) if (reverse != null)
sb.append(" Reverse: " + reverse + "\n"); sb.append(" Reverse: ").append(reverse).append("\n");
sb.append("]"); sb.append("]");
return sb.toString(); return sb.toString();
} }
......
...@@ -31,6 +31,7 @@ import java.security.cert.CRLReason; ...@@ -31,6 +31,7 @@ import java.security.cert.CRLReason;
import java.security.cert.X509CRLEntry; import java.security.cert.X509CRLEntry;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap; import java.util.HashMap;
...@@ -500,6 +501,9 @@ public class X509CRLEntryImpl extends X509CRLEntry { ...@@ -500,6 +501,9 @@ public class X509CRLEntryImpl extends X509CRLEntry {
} }
public Map<String, java.security.cert.Extension> getExtensions() { public Map<String, java.security.cert.Extension> getExtensions() {
if (extensions == null) {
return Collections.emptyMap();
}
Collection<Extension> exts = extensions.getAllExtensions(); Collection<Extension> exts = extensions.getAllExtensions();
HashMap<String, java.security.cert.Extension> map = HashMap<String, java.security.cert.Extension> map =
new HashMap<String, java.security.cert.Extension>(exts.size()); new HashMap<String, java.security.cert.Extension>(exts.size());
......
/*
* Copyright (c) 2012, 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.
*
* 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.
*/
/**
* @test
* @bug 6854712
* @summary Basic unit test for PKIXRevocationChecker
*/
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPathChecker;
import java.security.cert.CertPathValidator;
import java.security.cert.Extension;
import java.security.cert.PKIXRevocationChecker;
import java.security.cert.PKIXRevocationChecker.Option;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class UnitTest {
public static void main(String[] args) throws Exception {
CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
CertPathChecker cpc = cpv.getRevocationChecker();
PKIXRevocationChecker prc = (PKIXRevocationChecker)cpc;
System.out.println("Testing that get methods return null or " +
"empty lists/sets/maps");
requireNull(prc.getOCSPResponder(), "getOCSPResponder()");
requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
requireEmpty(prc.getOCSPStapledResponses(),
"getOCSPStapledResponses()");
requireEmpty(prc.getOptions(), "getOptions()");
System.out.println("Testing that get methods return same parameters " +
"that are passed to set methods");
URI uri = new URI("http://localhost");
prc.setOCSPResponder(uri);
requireEquals(uri, prc.getOCSPResponder(), "getOCSPResponder()");
X509Certificate cert = getCert();
prc.setOCSPResponderCert(cert);
requireEquals(cert, prc.getOCSPResponderCert(),
"getOCSPResponderCert()");
List<Extension> exts = new ArrayList<>();
for (String oid : cert.getNonCriticalExtensionOIDs()) {
System.out.println(oid);
exts.add(new ExtensionImpl(oid,
cert.getExtensionValue(oid), false));
}
prc.setOCSPExtensions(exts);
requireEquals(exts, prc.getOCSPExtensions(), "getOCSPExtensions()");
Set<Option> options = EnumSet.of(Option.ONLY_END_ENTITY);
prc.setOptions(options);
requireEquals(options, prc.getOptions(), "getOptions()");
System.out.println("Testing that parameters are re-initialized to " +
"default values if null is passed to set methods");
prc.setOCSPResponder(null);
requireNull(prc.getOCSPResponder(), "getOCSPResponder()");
prc.setOCSPResponderCert(null);
requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
prc.setOCSPExtensions(null);
requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
prc.setOCSPStapledResponses(null);
requireEmpty(prc.getOCSPStapledResponses(),
"getOCSPStapledResponses()");
prc.setOptions(null);
requireEmpty(prc.getOptions(), "getOptions()");
}
static void requireNull(Object o, String msg) throws Exception {
if (o != null) {
throw new Exception("FAILED: " + msg + " must return null");
}
}
static void requireEmpty(Map<?,?> m, String msg) throws Exception {
if (!m.isEmpty()) {
throw new Exception("FAILED: " + msg + " must return an empty map");
}
}
static void requireEmpty(List<?> l, String msg) throws Exception {
if (!l.isEmpty()) {
throw new Exception("FAILED: " + msg +" must return an empty list");
}
}
static void requireEmpty(Set<?> s, String msg) throws Exception {
if (!s.isEmpty()) {
throw new Exception("FAILED: " + msg + " must return an empty set");
}
}
static void requireEquals(Object a, Object b, String msg) throws Exception {
if (!a.equals(b)) {
throw new Exception("FAILED: " + msg + " does not return the " +
"same object that was set");
}
}
static X509Certificate getCert() throws Exception {
String b64 =
"-----BEGIN CERTIFICATE-----\n" +
"MIIBLTCB2KADAgECAgEDMA0GCSqGSIb3DQEBBAUAMA0xCzAJBgNVBAMTAkNBMB4X\n" +
"DTAyMTEwNzExNTcwM1oXDTIyMTEwNzExNTcwM1owFTETMBEGA1UEAxMKRW5kIEVu\n" +
"dGl0eTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDVBDfF+uBr5s5jzzDs1njKlZNt\n" +
"h8hHzEt3ASh67Peos+QrDzgpUyFXT6fdW2h7iPf0ifjM8eW2xa+3EnPjjU5jAgMB\n" +
"AAGjGzAZMBcGA1UdIAQQMA4wBgYEVR0gADAEBgIqADANBgkqhkiG9w0BAQQFAANB\n" +
"AFo//WOboCNOCcA1fvcWW9oc4MvV8ZPvFIAbyEbgyFd4id5lGDTRbRPvvNZRvdsN\n" +
"NM2gXYr+f87NHIXc9EF3pzw=\n" +
"-----END CERTIFICATE-----";
InputStream is = new ByteArrayInputStream(b64.getBytes("UTF-8"));
CertificateFactory cf = CertificateFactory.getInstance("X.509");
return (X509Certificate)cf.generateCertificate(is);
}
static class ExtensionImpl implements Extension {
private final String oid;
private final byte[] val;
private final boolean critical;
ExtensionImpl(String oid, byte[] val, boolean critical) {
this.oid = oid;
this.val = val;
this.critical = critical;
}
public void encode(OutputStream out) throws IOException {
throw new UnsupportedOperationException();
}
public String getId() {
return oid;
}
public byte[] getValue() {
return val.clone();
}
public boolean isCritical() {
return critical;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册