6854712: Revocation checking enhancements (JEP-124)

6637288: Add OCSP support to PKIX CertPathBuilder implementation
7126011: ReverseBuilder.getMatchingCACerts may throws NPE

Reviewed-by: xuelei
This commit is contained in:
Sean Mullan 2012-05-30 17:19:46 -04:00
parent 830a24d326
commit 14c586557e
41 changed files with 3257 additions and 2776 deletions

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -45,15 +45,28 @@ import sun.security.jca.GetInstance.Instance;
* one of the static <code>getInstance</code> methods, passing in the
* algorithm name of the <code>CertPathBuilder</code> desired and optionally
* 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
* passing it an algorithm-specific set of parameters. If successful, the
* result (including the <code>CertPath</code> that was built) is returned
* in an object that implements the <code>CertPathBuilderResult</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 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:
* <ul>
* <li><tt>PKIX</tt></li>
@ -96,10 +109,9 @@ public class CertPathBuilder {
* </pre>
*/
private static final String CPB_TYPE = "certpathbuilder.type";
private static final Debug debug = Debug.getInstance("certpath");
private CertPathBuilderSpi builderSpi;
private Provider provider;
private String algorithm;
private final CertPathBuilderSpi builderSpi;
private final Provider provider;
private final String algorithm;
/**
* Creates a <code>CertPathBuilder</code> object of the given algorithm,
@ -290,15 +302,30 @@ public class CertPathBuilder {
* if no such property exists.
*/
public final static String getDefaultType() {
String cpbtype;
cpbtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(CPB_TYPE);
}
});
if (cpbtype == null) {
cpbtype = "PKIX";
}
return cpbtype;
String cpbtype =
AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(CPB_TYPE);
}
});
return (cpbtype == null) ? "PKIX" : 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();
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -72,4 +72,25 @@ public abstract class CertPathBuilderSpi {
*/
public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
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();
}
}

View File

@ -0,0 +1,77 @@
/*
* 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;
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -46,15 +46,29 @@ import sun.security.jca.GetInstance.Instance;
* call one of the static <code>getInstance</code> methods, passing in the
* algorithm name of the <code>CertPathValidator</code> desired and
* 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
* validate} method and passing it the <code>CertPath</code> to be validated
* and an algorithm-specific set of parameters. If successful, the result is
* returned in an object that implements the
* <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:
* <ul>
* <li><tt>PKIX</tt></li>
@ -96,10 +110,9 @@ public class CertPathValidator {
* </pre>
*/
private static final String CPV_TYPE = "certpathvalidator.type";
private static final Debug debug = Debug.getInstance("certpath");
private CertPathValidatorSpi validatorSpi;
private Provider provider;
private String algorithm;
private final CertPathValidatorSpi validatorSpi;
private final Provider provider;
private final String algorithm;
/**
* Creates a <code>CertPathValidator</code> object of the given algorithm,
@ -301,15 +314,30 @@ public class CertPathValidator {
* if no such property exists.
*/
public final static String getDefaultType() {
String cpvtype;
cpvtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(CPV_TYPE);
}
});
if (cpvtype == null) {
cpvtype = "PKIX";
}
return cpvtype;
String cpvtype =
AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return Security.getProperty(CPV_TYPE);
}
});
return (cpvtype == null) ? "PKIX" : 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();
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -82,4 +82,25 @@ public abstract class CertPathValidatorSpi {
public abstract CertPathValidatorResult
engineValidate(CertPath certPath, CertPathParameters params)
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();
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -87,7 +87,8 @@ import java.util.Set;
* @author Yassir Elley
* @author Sean Mullan
*/
public abstract class PKIXCertPathChecker implements Cloneable {
public abstract class PKIXCertPathChecker
implements CertPathChecker, Cloneable {
/**
* Default constructor.
@ -111,6 +112,7 @@ public abstract class PKIXCertPathChecker implements Cloneable {
* the specified order; it should never be thrown if the forward flag
* is false since reverse checking must be supported
*/
@Override
public abstract void init(boolean forward)
throws CertPathValidatorException;
@ -123,6 +125,7 @@ public abstract class PKIXCertPathChecker implements Cloneable {
* @return <code>true</code> if forward checking is supported,
* <code>false</code> otherwise
*/
@Override
public abstract boolean isForwardCheckingSupported();
/**
@ -162,6 +165,17 @@ public abstract class PKIXCertPathChecker implements Cloneable {
Collection<String> unresolvedCritExts)
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>
* method.
@ -170,6 +184,7 @@ public abstract class PKIXCertPathChecker implements Cloneable {
*
* @return a copy of this <code>PKIXCertPathChecker</code>
*/
@Override
public Object clone() {
try {
return super.clone();

View File

@ -0,0 +1,271 @@
/*
* 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
}
}

View File

@ -1,5 +1,5 @@
<!--
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.
This code is free software; you can redistribute it and/or modify it
@ -38,8 +38,10 @@ certificates and X.509 v2 CRLs.
<li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
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
<li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate
Status Protocol - OCSP
<li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
Cryptography Architecture Standard Algorithm Name
@ -50,8 +52,8 @@ certificates and X.509 v2 CRLs.
For information about X.509 certificates and CRLs, please see:
<ul>
<li><a href="http://www.ietf.org/rfc/rfc3280.txt">
http://www.ietf.org/rfc/rfc3280.txt</a>
<li><a href="http://www.ietf.org/rfc/rfc5280.txt">
http://www.ietf.org/rfc/rfc5280.txt</a>
<li><a href=
"{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html">
<b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,13 +24,11 @@
*/
package sun.security.provider.certpath;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* An AdjacencyList is used to store the history of certification paths
* attempted in constructing a path from an initiator to a target. The
@ -123,124 +121,117 @@ public class AdjacencyList {
* at the start.
*/
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
// from the global list. So, we have to start by getting the list
// that contains the set of Vertexes we're considering.
List<Vertex> l = theList.get(index);
try {
// we're interested in the case where all indexes are -1...
boolean allNegOne = true;
// ...and in the case where every entry has a Throwable
boolean allXcps = true;
// we're interested in the case where all indexes are -1...
boolean allNegOne = true;
// ...and in the case where every entry has a Throwable
boolean allXcps = true;
for (Vertex v : l) {
if (v.getIndex() != -1) {
// count an empty list the same as an index of -1...this
// is to patch a bug somewhere in the builder
if (theList.get(v.getIndex()).size() != 0)
allNegOne = false;
} else {
if (v.getThrowable() == null)
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));
}
if (allNegOne) {
// There are two cases that we could be looking at here. We
// may need to back up, or the build may have succeeded at
// this point. This is based on whether or not any
// exceptions were found in the list.
if (allXcps) {
// we need to go back...see if this is the last one
if (follow == null)
mStepList.add(new BuildStep(null, BuildStep.FAIL));
else
mStepList.add(new BuildStep(follow.getVertex(),
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<>();
for (Vertex v : l) {
if (v.getThrowable() == null)
possibles.add(v);
}
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));
}
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) {
if (v.getIndex() != -1) {
// count an empty list the same as an index of -1...this
// is to patch a bug somewhere in the builder
if (theList.get(v.getIndex()).size() != 0)
allNegOne = false;
}
else
if (v.getThrowable() == null)
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));
// Note that we'll only find a SUCCEED case when we're
// looking at the last possible path, so we don't need to
// consider success in the while loop
if (v.getIndex() != -1) {
if (theList.get(v.getIndex()).size() != 0) {
// If the entry we're looking at doesn't have an
// index of -1, and doesn't lead to an empty list,
// then it's something we follow!
BuildStep bs = new BuildStep(v, BuildStep.FOLLOW);
mStepList.add(bs);
success = buildList(theList, v.getIndex(), bs);
}
}
}
if (allNegOne) {
// There are two cases that we could be looking at here. We
// may need to back up, or the build may have succeeded at
// this point. This is based on whether or not any
// exceptions were found in the list.
if (allXcps) {
// we need to go back...see if this is the last one
if (follow == null)
mStepList.add(new BuildStep(null, BuildStep.FAIL));
else
mStepList.add(new BuildStep(follow.getVertex(),
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) {
// 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));
}
return true;
}
if (success) {
// We're already finished!
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;
// We failed, and we've exhausted all the paths that we
// could take. The only choice is to back ourselves out.
if (follow == null)
mStepList.add(new BuildStep(null, BuildStep.FAIL));
else
mStepList.add(new BuildStep(follow.getVertex(),
BuildStep.BACK));
for (Vertex v : l) {
// Note that we'll only find a SUCCEED case when we're
// looking at the last possible path, so we don't need to
// consider success in the while loop
if (v.getIndex() != -1) {
if (theList.get(v.getIndex()).size() != 0) {
// If the entry we're looking at doesn't have an
// index of -1, and doesn't lead to an empty list,
// then it's something we follow!
BuildStep bs = new BuildStep(v, BuildStep.FOLLOW);
mStepList.add(bs);
success = buildList(theList, v.getIndex(), bs);
}
}
}
if (success) {
// We're already finished!
return true;
} else {
// We failed, and we've exhausted all the paths that we
// could take. The only choice is to back ourselves out.
if (follow == null)
mStepList.add(new BuildStep(null, BuildStep.FAIL));
else
mStepList.add(new BuildStep(follow.getVertex(),
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 {
*
* @return String representation
*/
@Override
public String toString() {
String out = "[\n";
StringBuilder sb = new StringBuilder("[\n");
int i = 0;
for (List<Vertex> l : mOrigList) {
out = out + "LinkedList[" + i++ + "]:\n";
sb.append("LinkedList[").append(i++).append("]:\n");
for (Vertex step : l) {
try {
out = out + step.toString();
out = out + "\n";
}
catch (Exception e) { out = out + "No Such Element\n"; }
sb.append(step.toString()).append("\n");
}
}
out = out + "]\n";
sb.append("]\n");
return out;
return sb.toString();
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -62,7 +62,7 @@ class BasicChecker extends PKIXCertPathChecker {
private static final Debug debug = Debug.getInstance("certpath");
private final PublicKey trustedPubKey;
private final X500Principal caName;
private final Date testDate;
private final Date date;
private final String sigProvider;
private final boolean sigOnly;
private X500Principal prevSubject;
@ -73,14 +73,13 @@ class BasicChecker extends PKIXCertPathChecker {
*
* @param anchor the anchor selected to validate the target 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 sigOnly true if only signature checking is to be done;
* if false, all checks are done
*/
BasicChecker(TrustAnchor anchor, Date testDate, String sigProvider,
boolean sigOnly) throws CertPathValidatorException
{
BasicChecker(TrustAnchor anchor, Date date, String sigProvider,
boolean sigOnly) {
if (anchor.getTrustedCert() != null) {
this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
this.caName = anchor.getTrustedCert().getSubjectX500Principal();
@ -88,16 +87,16 @@ class BasicChecker extends PKIXCertPathChecker {
this.trustedPubKey = anchor.getCAPublicKey();
this.caName = anchor.getCA();
}
this.testDate = testDate;
this.date = date;
this.sigProvider = sigProvider;
this.sigOnly = sigOnly;
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) {
prevPubKey = trustedPubKey;
@ -108,10 +107,12 @@ class BasicChecker extends PKIXCertPathChecker {
}
}
@Override
public boolean isForwardCheckingSupported() {
return false;
}
@Override
public Set<String> getSupportedExtensions() {
return null;
}
@ -124,33 +125,31 @@ class BasicChecker extends PKIXCertPathChecker {
* @param cert the Certificate
* @param unresolvedCritExts a Collection of the unresolved critical
* extensions
* @exception CertPathValidatorException Exception thrown if certificate
* does not verify.
* @throws CertPathValidatorException if certificate does not verify
*/
@Override
public void check(Certificate cert, Collection<String> unresolvedCritExts)
throws CertPathValidatorException
{
X509Certificate currCert = (X509Certificate) cert;
X509Certificate currCert = (X509Certificate)cert;
if (!sigOnly) {
verifyTimestamp(currCert, testDate);
verifyNameChaining(currCert, prevSubject);
verifyTimestamp(currCert);
verifyNameChaining(currCert);
}
verifySignature(currCert, prevPubKey, sigProvider);
verifySignature(currCert);
updateState(currCert);
}
/**
* Verifies the signature on the certificate using the previous public key
* @param cert the Certificate
* @param prevPubKey the previous PublicKey
* @param sigProvider a String containing the signature provider
* @exception CertPathValidatorException Exception thrown if certificate
* does not verify.
* Verifies the signature on the certificate using the previous public key.
*
* @param cert the X509Certificate
* @throws CertPathValidatorException if certificate does not verify
*/
private void verifySignature(X509Certificate cert, PublicKey prevPubKey,
String sigProvider) throws CertPathValidatorException
private void verifySignature(X509Certificate cert)
throws CertPathValidatorException
{
String msg = "signature";
if (debug != null)
@ -162,7 +161,7 @@ class BasicChecker extends PKIXCertPathChecker {
throw new CertPathValidatorException
(msg + " check failed", e, null, -1,
BasicReason.INVALID_SIGNATURE);
} catch (Exception e) {
} catch (GeneralSecurityException e) {
throw new CertPathValidatorException(msg + " check failed", e);
}
@ -173,7 +172,7 @@ class BasicChecker extends PKIXCertPathChecker {
/**
* Internal method to verify the timestamp on a certificate
*/
private void verifyTimestamp(X509Certificate cert, Date date)
private void verifyTimestamp(X509Certificate cert)
throws CertPathValidatorException
{
String msg = "timestamp";
@ -197,8 +196,8 @@ class BasicChecker extends PKIXCertPathChecker {
/**
* Internal method to check that cert has a valid DN to be next in a chain
*/
private void verifyNameChaining(X509Certificate cert,
X500Principal prevSubject) throws CertPathValidatorException
private void verifyNameChaining(X509Certificate cert)
throws CertPathValidatorException
{
if (prevSubject != null) {
@ -207,8 +206,8 @@ class BasicChecker extends PKIXCertPathChecker {
debug.println("---checking " + msg + "...");
X500Principal currIssuer = cert.getIssuerX500Principal();
// reject null or empty issuer DNs
// reject null or empty issuer DNs
if (X500Name.asX500Name(currIssuer).isEmpty()) {
throw new CertPathValidatorException
(msg + " check failed: " +

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,6 @@
package sun.security.provider.certpath;
import sun.security.util.Debug;
import java.security.cert.X509Certificate;
/**
@ -39,7 +38,6 @@ import java.security.cert.X509Certificate;
*/
public class BuildStep {
private static final Debug debug = Debug.getInstance("certpath");
private Vertex vertex;
private X509Certificate cert;
private Throwable throwable;
@ -86,7 +84,7 @@ public class BuildStep {
public BuildStep(Vertex vtx, int res) {
vertex = vtx;
if (vertex != null) {
cert = (X509Certificate)vertex.getCertificate();
cert = vertex.getCertificate();
throwable = vertex.getThrowable();
}
result = res;
@ -117,7 +115,7 @@ public class BuildStep {
* @returns String form of issuer name or null, if no certificate.
*/
public String getIssuerName() {
return (cert == null ? null : cert.getIssuerX500Principal().toString());
return getIssuerName(null);
}
/**
@ -142,7 +140,7 @@ public class BuildStep {
* @returns String form of subject name or null, if no certificate.
*/
public String getSubjectName() {
return (cert == null ? null : cert.getSubjectX500Principal().toString());
return getSubjectName(null);
}
/**
@ -191,21 +189,21 @@ public class BuildStep {
public String resultToString(int res) {
String resultString = "";
switch (res) {
case BuildStep.POSSIBLE:
case POSSIBLE:
resultString = "Certificate to be tried.\n";
break;
case BuildStep.BACK:
case BACK:
resultString = "Certificate backed out since path does not "
+ "satisfy build requirements.\n";
break;
case BuildStep.FOLLOW:
case FOLLOW:
resultString = "Certificate satisfies conditions.\n";
break;
case BuildStep.FAIL:
case FAIL:
resultString = "Certificate backed out since path does not "
+ "satisfy conditions.\n";
break;
case BuildStep.SUCCEED:
case SUCCEED:
resultString = "Certificate satisfies conditions.\n";
break;
default:
@ -220,6 +218,7 @@ public class BuildStep {
*
* @returns String
*/
@Override
public String toString() {
String out = "Internal Error\n";
switch (result) {
@ -273,8 +272,6 @@ public class BuildStep {
* @returns String
*/
public String fullToString() {
String out = resultToString(getResult());
out = out + vertex.toString();
return out;
return resultToString(getResult()) + vertex.toString();
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,9 +31,8 @@ import java.security.GeneralSecurityException;
import java.security.cert.*;
import java.util.*;
import javax.security.auth.x500.X500Principal;
import sun.security.action.GetBooleanAction;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
import sun.security.x509.GeneralNames;
import sun.security.x509.GeneralNameInterface;
@ -56,9 +55,7 @@ public abstract class Builder {
private static final Debug debug = Debug.getInstance("certpath");
private Set<String> matchingPolicies;
final PKIXBuilderParameters buildParams;
final X500Principal targetSubjectDN;
final Date date;
final BuilderParams buildParams;
final X509CertSelector targetCertConstraints;
/**
@ -74,14 +71,10 @@ public abstract class Builder {
*
* @param params the parameter set used to build a certification path
*/
Builder(PKIXBuilderParameters buildParams, X500Principal targetSubjectDN) {
Builder(BuilderParams 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 =
(X509CertSelector) buildParams.getTargetCertConstraints();
(X509CertSelector)buildParams.targetCertConstraints();
}
/**
@ -104,7 +97,8 @@ public abstract class Builder {
* @param certPathList the certPathList generated thus far
*/
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.
@ -123,7 +117,7 @@ public abstract class Builder {
* @param certPathList the certification path list
*/
abstract void addCertToPath(X509Certificate cert,
LinkedList<X509Certificate> certPathList);
LinkedList<X509Certificate> certPathList);
/**
* Removes final certificate from the certPathList
@ -147,7 +141,8 @@ public abstract class Builder {
* is a grandparent, etc.
*/
static int distance(GeneralNameInterface base,
GeneralNameInterface test, int incomparable) {
GeneralNameInterface test, int incomparable)
{
switch (base.constrains(test)) {
case GeneralNameInterface.NAME_DIFF_TYPE:
if (debug != null) {
@ -192,7 +187,8 @@ public abstract class Builder {
* some number of down hops.
*/
static int hops(GeneralNameInterface base, GeneralNameInterface test,
int incomparable) {
int incomparable)
{
int baseRtest = base.constrains(test);
switch (baseRtest) {
case GeneralNameInterface.NAME_DIFF_TYPE:
@ -282,9 +278,9 @@ public abstract class Builder {
* @throws IOException if certificate does not get closer
*/
static int targetDistance(NameConstraintsExtension constraints,
X509Certificate cert, GeneralNameInterface target)
throws IOException {
X509Certificate cert, GeneralNameInterface target)
throws IOException
{
/* ensure that certificate satisfies existing name constraints */
if (constraints != null && !constraints.verify(cert)) {
throw new IOException("certificate does not satisfy existing name "
@ -295,7 +291,7 @@ public abstract class Builder {
try {
certImpl = X509CertImpl.toImpl(cert);
} catch (CertificateException e) {
throw (IOException)new IOException("Invalid certificate").initCause(e);
throw new IOException("Invalid certificate", e);
}
/* see if certificate subject matches target */
X500Name subject = X500Name.asX500Name(certImpl.getSubjectX500Principal());
@ -398,13 +394,13 @@ public abstract class Builder {
*/
Set<String> getMatchingPolicies() {
if (matchingPolicies != null) {
Set<String> initialPolicies = buildParams.getInitialPolicies();
Set<String> initialPolicies = buildParams.initialPolicies();
if ((!initialPolicies.isEmpty()) &&
(!initialPolicies.contains(PolicyChecker.ANY_POLICY)) &&
(buildParams.isPolicyMappingInhibited()))
(buildParams.policyMappingInhibited()))
{
initialPolicies.add(PolicyChecker.ANY_POLICY);
matchingPolicies = initialPolicies;
matchingPolicies = new HashSet<>(initialPolicies);
matchingPolicies.add(PolicyChecker.ANY_POLICY);
} else {
// we just return an empty set to make sure that there is
// at least a certificate policies extension in the cert
@ -429,13 +425,15 @@ public abstract class Builder {
* Returns true iff resultCerts changed (a cert was added to the collection)
*/
boolean addMatchingCerts(X509CertSelector selector,
Collection<CertStore> certStores,
Collection<X509Certificate> resultCerts, boolean checkAll) {
Collection<CertStore> certStores,
Collection<X509Certificate> resultCerts,
boolean checkAll)
{
X509Certificate targetCert = selector.getCertificate();
if (targetCert != null) {
// no need to search CertStores
if (selector.match(targetCert) && !X509CertImpl.isSelfSigned
(targetCert, buildParams.getSigProvider())) {
(targetCert, buildParams.sigProvider())) {
if (debug != null) {
debug.println("Builder.addMatchingCerts: adding target cert");
}
@ -450,7 +448,7 @@ public abstract class Builder {
store.getCertificates(selector);
for (Certificate cert : certs) {
if (!X509CertImpl.isSelfSigned
((X509Certificate)cert, buildParams.getSigProvider())) {
((X509Certificate)cert, buildParams.sigProvider())) {
if (resultCerts.add((X509Certificate)cert)) {
add = true;
}
@ -471,16 +469,4 @@ public abstract class Builder {
}
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);
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -83,9 +83,8 @@ public abstract class CertStoreHelper {
= (CertStoreHelper)c.newInstance();
cache.put(type, csh);
return csh;
} catch (InstantiationException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
} catch (InstantiationException |
IllegalAccessException e) {
throw new AssertionError(e);
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,7 +31,6 @@ import java.security.cert.CRL;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Iterator;
import java.security.cert.CertSelector;
import java.security.cert.CertStore;
import java.security.cert.CertStoreException;
@ -114,6 +113,7 @@ public class CollectionCertStore extends CertStoreSpi {
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
@Override
public Collection<Certificate> engineGetCertificates
(CertSelector selector) throws CertStoreException {
if (coll == null) {
@ -122,18 +122,15 @@ public class CollectionCertStore extends CertStoreSpi {
// Tolerate a few ConcurrentModificationExceptions
for (int c = 0; c < 10; c++) {
try {
HashSet<Certificate> result = new HashSet<Certificate>();
Iterator<?> i = coll.iterator();
HashSet<Certificate> result = new HashSet<>();
if (selector != null) {
while (i.hasNext()) {
Object o = i.next();
for (Object o : coll) {
if ((o instanceof Certificate) &&
selector.match((Certificate) o))
result.add((Certificate)o);
}
} else {
while (i.hasNext()) {
Object o = i.next();
for (Object o : coll) {
if (o instanceof Certificate)
result.add((Certificate)o);
}
@ -157,6 +154,7 @@ public class CollectionCertStore extends CertStoreSpi {
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
@Override
public Collection<CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException
{
@ -166,22 +164,19 @@ public class CollectionCertStore extends CertStoreSpi {
// Tolerate a few ConcurrentModificationExceptions
for (int c = 0; c < 10; c++) {
try {
HashSet<CRL> result = new HashSet<CRL>();
Iterator<?> i = coll.iterator();
HashSet<CRL> result = new HashSet<>();
if (selector != null) {
while (i.hasNext()) {
Object o = i.next();
for (Object o : coll) {
if ((o instanceof CRL) && selector.match((CRL) o))
result.add((CRL)o);
}
} else {
while (i.hasNext()) {
Object o = i.next();
for (Object o : coll) {
if (o instanceof CRL)
result.add((CRL)o);
}
}
return(result);
return result;
} catch (ConcurrentModificationException e) { }
}
throw new ConcurrentModificationException("Too many "

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,19 +25,20 @@
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.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.X509Certificate;
import java.security.cert.PKIXCertPathChecker;
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.x509.PKIXExtensions;
import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.X509CertImpl;
@ -66,13 +67,12 @@ class ConstraintsChecker extends PKIXCertPathChecker {
* Creates a ConstraintsChecker.
*
* @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;
init(false);
}
@Override
public void init(boolean forward) throws CertPathValidatorException {
if (!forward) {
i = 0;
@ -84,15 +84,17 @@ class ConstraintsChecker extends PKIXCertPathChecker {
}
}
@Override
public boolean isForwardCheckingSupported() {
return false;
}
@Override
public Set<String> getSupportedExtensions() {
if (supportedExts == null) {
supportedExts = new HashSet<String>();
supportedExts.add(PKIXExtensions.BasicConstraints_Id.toString());
supportedExts.add(PKIXExtensions.NameConstraints_Id.toString());
supportedExts = new HashSet<String>(2);
supportedExts.add(BasicConstraints_Id.toString());
supportedExts.add(NameConstraints_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts);
}
return supportedExts;
@ -104,14 +106,15 @@ class ConstraintsChecker extends PKIXCertPathChecker {
*
* @param cert the <code>Certificate</code> to be checked
* @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
* does not pass the check
* does not pass the check
*/
@Override
public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException
{
X509Certificate currCert = (X509Certificate) cert;
X509Certificate currCert = (X509Certificate)cert;
i++;
// MUST run NC check second, since it depends on BC check to
@ -120,8 +123,8 @@ class ConstraintsChecker extends PKIXCertPathChecker {
verifyNameConstraints(currCert);
if (unresCritExts != null && !unresCritExts.isEmpty()) {
unresCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString());
unresCritExts.remove(PKIXExtensions.NameConstraints_Id.toString());
unresCritExts.remove(BasicConstraints_Id.toString());
unresCritExts.remove(NameConstraints_Id.toString());
}
}
@ -166,9 +169,9 @@ class ConstraintsChecker extends PKIXCertPathChecker {
/**
* Helper to fold sets of name constraints together
*/
static NameConstraintsExtension
mergeNameConstraints(X509Certificate currCert,
NameConstraintsExtension prevNC) throws CertPathValidatorException
static NameConstraintsExtension mergeNameConstraints(
X509Certificate currCert, NameConstraintsExtension prevNC)
throws CertPathValidatorException
{
X509CertImpl currCertImpl;
try {
@ -197,7 +200,7 @@ class ConstraintsChecker extends PKIXCertPathChecker {
// Make sure we do a clone here, because we're probably
// going to modify this object later and we don't want to
// be sharing it with a Certificate object!
return (NameConstraintsExtension) newConstraints.clone();
return (NameConstraintsExtension)newConstraints.clone();
}
} else {
try {

View File

@ -1,785 +0,0 @@
/*
* Copyright (c) 2000, 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.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.HashSet;
import java.util.Set;
import java.util.Iterator;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.cert.*;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.interfaces.DSAPublicKey;
import sun.security.util.Debug;
import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension;
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 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
// validity of CRLs
private static final long MAX_CLOCK_SKEW = 900000;
/**
* Creates a <code>CrlRevocationChecker</code>.
*
* @param anchor anchor selected to validate the target certificate
* @param params <code>PKIXParameters</code> to be used for
* finding certificates and CRLs, etc.
*/
CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params)
throws CertPathValidatorException
{
this(anchor, params, null);
}
/**
* Creates a <code>CrlRevocationChecker</code>, allowing
* 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);
}
CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
Collection<X509Certificate> certs, boolean onlyEECert)
throws CertPathValidatorException {
mAnchor = anchor;
mParams = params;
mStores = new ArrayList<CertStore>(params.getCertStores());
mSigProvider = params.getSigProvider();
if (certs != null) {
try {
mStores.add(CertStore.getInstance("Collection",
new CollectionCertStoreParameters(certs)));
} catch (Exception e) {
// should never occur but not necessarily fatal, so log it,
// ignore and continue
if (debug != null) {
debug.println("CrlRevocationChecker: " +
"error creating Collection CertStore: " + e);
}
}
}
Date testDate = params.getDate();
mCurrentTime = (testDate != null ? testDate : new Date());
mOnlyEECert = onlyEECert;
init(false);
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor
*/
public void init(boolean forward) throws CertPathValidatorException
{
if (!forward) {
if (mAnchor != null) {
if (mAnchor.getCAPublicKey() != null) {
mPrevPubKey = mAnchor.getCAPublicKey();
} else {
mPrevPubKey = mAnchor.getTrustedCert().getPublicKey();
}
} else {
mPrevPubKey = null;
}
mCRLSignFlag = true;
} else {
throw new CertPathValidatorException("forward checking "
+ "not supported");
}
}
public boolean isForwardCheckingSupported() {
return false;
}
public Set<String> getSupportedExtensions() {
return null;
}
/**
* 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)
throws CertPathValidatorException
{
X509Certificate currCert = (X509Certificate) cert;
verifyRevocationStatus(currCert, mPrevPubKey, mCRLSignFlag, true);
// Make new public key if parameters are missing
PublicKey cKey = currCert.getPublicKey();
if (cKey instanceof DSAPublicKey &&
((DSAPublicKey)cKey).getParams() == null) {
// cKey needs to inherit DSA parameters from prev key
cKey = BasicChecker.makeInheritedParamsKey(cKey, mPrevPubKey);
}
mPrevPubKey = cKey;
mCRLSignFlag = certCanSignCrl(currCert);
}
/**
* Performs the revocation status check on the certificate using
* the provided state variables, as well as the constant internal
* 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);
return certCanSignCrl(currCert);
}
/**
* Checks that a cert can be used to verify a CRL.
*
* @param currCert 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 currCert) {
// if the cert doesn't include the key usage ext, or
// the key usage ext asserts cRLSigning, return true,
// otherwise return false.
boolean[] kbools = currCert.getKeyUsage();
if (kbools != null) {
return kbools[6];
}
return false;
}
/**
* Internal method to start the verification of a cert
*/
private void verifyRevocationStatus(X509Certificate currCert,
PublicKey prevKey, boolean signFlag, boolean allowSeparateKey)
throws CertPathValidatorException
{
verifyRevocationStatus(currCert, prevKey, signFlag,
allowSeparateKey, null, mParams.getTrustAnchors());
}
/**
* Internal method to start the verification of a cert
* @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
* whose revocation status depends on the
* non-revoked status of this cert. To avoid
* 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) {
debug.println("CrlRevocationChecker.verifyRevocationStatus()" +
" ---checking " + msg + "...");
}
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
// to handle this, so we feel it is safest to reject them until
// the issue is resolved in the PKIX WG.
if ((stackedCerts != null) && stackedCerts.contains(currCert)) {
if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus()" +
" circular dependency");
}
throw new CertPathValidatorException
("Could not determine revocation status", null, null, -1,
BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
// init the state for this run
mPossibleCRLs = new HashSet<X509CRL>();
mApprovedCRLs = new HashSet<X509CRL>();
boolean[] reasonsMask = new boolean[9];
try {
X509CRLSelector sel = new X509CRLSelector();
sel.setCertificateChecking(currCert);
CertPathHelper.setDateAndTime(sel, mCurrentTime, MAX_CLOCK_SKEW);
for (CertStore mStore : mStores) {
for (java.security.cert.CRL crl : mStore.getCRLs(sel)) {
mPossibleCRLs.add((X509CRL)crl);
}
}
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) {
debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
"crls.size() = " + mPossibleCRLs.size());
}
if (!mPossibleCRLs.isEmpty()) {
// Now that we have a list of possible CRLs, see which ones can
// be approved
mApprovedCRLs.addAll(verifyPossibleCRLs(mPossibleCRLs, currCert,
signFlag, prevKey, reasonsMask, trustAnchors));
}
if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
"approved crls.size() = " + mApprovedCRLs.size());
}
// make sure that we have at least one CRL that _could_ cover
// the certificate in question and all reasons are covered
if (mApprovedCRLs.isEmpty() ||
!Arrays.equals(reasonsMask, ALL_REASONS)) {
if (allowSeparateKey) {
verifyWithSeparateSigningKey(currCert, prevKey, signFlag,
stackedCerts);
return;
} else {
throw new CertPathValidatorException
("Could not determine revocation status", null, null, -1,
BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
// See if the cert is in the set of approved crls.
if (debug != null) {
BigInteger sn = currCert.getSerialNumber();
debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
"starting the final sweep...");
debug.println("CrlRevocationChecker.verifyRevocationStatus" +
" cert SN: " + sn.toString());
}
CRLReason reasonCode = CRLReason.UNSPECIFIED;
X509CRLEntryImpl entry = null;
for (X509CRL crl : mApprovedCRLs) {
X509CRLEntry e = crl.getRevokedCertificate(currCert);
if (e != null) {
try {
entry = X509CRLEntryImpl.toImpl(e);
} catch (CRLException ce) {
throw new CertPathValidatorException(ce);
}
if (debug != null) {
debug.println("CrlRevocationChecker.verifyRevocationStatus"
+ " CRL entry: " + entry.toString());
}
/*
* Abort CRL validation and throw exception if there are any
* unrecognized critical CRL entry extensions (see section
* 5.3 of RFC 3280).
*/
Set<String> unresCritExts = entry.getCriticalExtensionOIDs();
if (unresCritExts != null && !unresCritExts.isEmpty()) {
/* remove any that we will process */
unresCritExts.remove
(PKIXExtensions.ReasonCode_Id.toString());
unresCritExts.remove
(PKIXExtensions.CertificateIssuer_Id.toString());
if (!unresCritExts.isEmpty()) {
if (debug != null) {
debug.println("Unrecognized "
+ "critical extension(s) in revoked CRL entry: "
+ unresCritExts);
}
throw new CertPathValidatorException
("Could not determine revocation status", null, null,
-1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
reasonCode = entry.getRevocationReason();
if (reasonCode == null) {
reasonCode = CRLReason.UNSPECIFIED;
}
Throwable t = new CertificateRevokedException
(entry.getRevocationDate(), reasonCode,
crl.getIssuerX500Principal(), entry.getExtensions());
throw new CertPathValidatorException(t.getMessage(), t,
null, -1, BasicReason.REVOKED);
}
}
}
/**
* 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
* find a valid CRL issued by a separate key that can verify the
* revocation status of this certificate.
* <p>
* Note that this does not provide support for indirect CRLs,
* only CRLs signed with a different key (but the same issuer
* name) as the certificate being checked.
*
* @param currCert the <code>X509Certificate</code> to be checked
* @param prevKey the <code>PublicKey</code> that failed
* @param signFlag <code>true</code> if that key was trusted to sign CRLs
* @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
* whose revocation status depends on the
* non-revoked status of this cert. To avoid
* circular dependencies, we assume they're
* revoked while checking the revocation
* status of this cert.
* @throws CertPathValidatorException if the cert's revocation status
* cannot be verified successfully with another key
*/
private void verifyWithSeparateSigningKey(X509Certificate currCert,
PublicKey prevKey, boolean signFlag, Set<X509Certificate> stackedCerts)
throws CertPathValidatorException {
String msg = "revocation status";
if (debug != null) {
debug.println(
"CrlRevocationChecker.verifyWithSeparateSigningKey()" +
" ---checking " + msg + "...");
}
// reject circular dependencies - RFC 3280 is not explicit on how
// to handle this, so we feel it is safest to reject them until
// the issue is resolved in the PKIX WG.
if ((stackedCerts != null) && stackedCerts.contains(currCert)) {
if (debug != null) {
debug.println(
"CrlRevocationChecker.verifyWithSeparateSigningKey()" +
" circular dependency");
}
throw new CertPathValidatorException
("Could not determine revocation status", null, null,
-1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
// If prevKey wasn't trusted, maybe we just didn't have the right
// path to it. Don't rule that key out.
if (!signFlag) {
prevKey = null;
}
// Try to find another key that might be able to sign
// CRLs vouching for this cert.
buildToNewKey(currCert, prevKey, stackedCerts);
}
/**
* Tries to find a CertPath that establishes a key that can be
* used to verify the revocation status of a given certificate.
* Ignores keys that have previously been tried. Throws a
* CertPathValidatorException if no such key could be found.
*
* @param currCert the <code>X509Certificate</code> to be checked
* @param prevKey the <code>PublicKey</code> of the certificate whose key
* cannot be used to vouch for the CRL and should be ignored
* @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
* whose revocation status depends on the
* establishment of this path.
* @throws CertPathValidatorException on failure
*/
private void buildToNewKey(X509Certificate currCert,
PublicKey prevKey, Set<X509Certificate> stackedCerts)
throws CertPathValidatorException {
if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" +
" starting work");
}
Set<PublicKey> badKeys = new HashSet<PublicKey>();
if (prevKey != null) {
badKeys.add(prevKey);
}
X509CertSelector certSel = new RejectKeySelector(badKeys);
certSel.setSubject(currCert.getIssuerX500Principal());
certSel.setKeyUsage(mCrlSignUsage);
Set<TrustAnchor> newAnchors =
(mAnchor == null ? mParams.getTrustAnchors() :
Collections.singleton(mAnchor));
PKIXBuilderParameters builderParams;
if (mParams instanceof PKIXBuilderParameters) {
builderParams = (PKIXBuilderParameters) mParams.clone();
builderParams.setTargetCertConstraints(certSel);
// Policy qualifiers must be rejected, since we don't have
// 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());
}
// Skip revocation during this build to detect circular
// references. But check revocation afterwards, using the
// key (or any other that works).
builderParams.setRevocationEnabled(false);
// check for AuthorityInformationAccess extension
if (Builder.USE_AIA == true) {
X509CertImpl currCertImpl = null;
try {
currCertImpl = X509CertImpl.toImpl(currCert);
} catch (CertificateException ce) {
// ignore but log it
if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey: " +
"error decoding cert: " + ce);
}
}
AuthorityInfoAccessExtension aiaExt = null;
if (currCertImpl != null) {
aiaExt = currCertImpl.getAuthorityInfoAccessExtension();
}
if (aiaExt != null) {
List<AccessDescription> adList = aiaExt.getAccessDescriptions();
if (adList != null) {
for (AccessDescription ad : adList) {
CertStore cs = URICertStore.getInstance(ad);
if (cs != null) {
if (debug != null) {
debug.println("adding AIAext CertStore");
}
builderParams.addCertStore(cs);
}
}
}
}
}
CertPathBuilder builder = null;
try {
builder = CertPathBuilder.getInstance("PKIX");
} catch (NoSuchAlgorithmException nsae) {
throw new CertPathValidatorException(nsae);
}
while (true) {
try {
if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" +
" about to try build ...");
}
PKIXCertPathBuilderResult cpbr =
(PKIXCertPathBuilderResult) builder.build(builderParams);
if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" +
" about to check revocation ...");
}
// Now check revocation of all certs in path, assuming that
// the stackedCerts are revoked.
if (stackedCerts == null) {
stackedCerts = new HashSet<X509Certificate>();
}
stackedCerts.add(currCert);
TrustAnchor ta = cpbr.getTrustAnchor();
PublicKey prevKey2 = ta.getCAPublicKey();
if (prevKey2 == null) {
prevKey2 = ta.getTrustedCert().getPublicKey();
}
boolean signFlag = true;
List<? extends Certificate> cpList =
cpbr.getCertPath().getCertificates();
try {
for (int i = cpList.size()-1; i >= 0; i-- ) {
X509Certificate cert = (X509Certificate) cpList.get(i);
if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()"
+ " index " + i + " checking " + cert);
}
verifyRevocationStatus(cert, prevKey2, signFlag, true,
stackedCerts, newAnchors);
signFlag = certCanSignCrl(cert);
prevKey2 = cert.getPublicKey();
}
} catch (CertPathValidatorException cpve) {
// ignore it and try to get another key
badKeys.add(cpbr.getPublicKey());
continue;
}
if (debug != null) {
debug.println("CrlRevocationChecker.buildToNewKey()" +
" got key " + cpbr.getPublicKey());
}
// Now check revocation on the current cert using that key.
// If it doesn't check out, try to find a different key.
// And if we can't find a key, then return false.
PublicKey newKey = cpbr.getPublicKey();
try {
verifyRevocationStatus(currCert, newKey, true, false);
// If that passed, the cert is OK!
return;
} catch (CertPathValidatorException cpve) {
// If it is revoked, rethrow exception
if (cpve.getReason() == BasicReason.REVOKED) {
throw cpve;
}
// Otherwise, ignore the exception and
// try to get another key.
}
badKeys.add(newKey);
} catch (InvalidAlgorithmParameterException iape) {
throw new CertPathValidatorException(iape);
} catch (CertPathBuilderException cpbe) {
throw new CertPathValidatorException
("Could not determine revocation status", null, null,
-1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
}
}
}
/*
* This inner class extends the X509CertSelector to add an additional
* check to make sure the subject public key isn't on a particular list.
* This class is used by buildToNewKey() to make sure the builder doesn't
* end up with a CertPath to a public key that has already been rejected.
*/
private static class RejectKeySelector extends X509CertSelector {
private final Set<PublicKey> badKeySet;
/**
* Creates a new <code>RejectKeySelector</code>.
*
* @param badPublicKeys a <code>Set</code> of
* <code>PublicKey</code>s that
* should be rejected (or <code>null</code>
* if no such check should be done)
*/
RejectKeySelector(Set<PublicKey> badPublicKeys) {
this.badKeySet = badPublicKeys;
}
/**
* Decides whether a <code>Certificate</code> should be selected.
*
* @param cert the <code>Certificate</code> to be checked
* @return <code>true</code> if the <code>Certificate</code> should be
* selected, <code>false</code> otherwise
*/
public boolean match(Certificate cert) {
if (!super.match(cert))
return(false);
if (badKeySet.contains(cert.getPublicKey())) {
if (debug != null)
debug.println("RejectCertSelector.match: bad key");
return false;
}
if (debug != null)
debug.println("RejectCertSelector.match: returning true");
return true;
}
/**
* Return a printable representation of the <code>CertSelector</code>.
*
* @return a <code>String</code> describing the contents of the
* <code>CertSelector</code>
*/
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("RejectCertSelector: [\n");
sb.append(super.toString());
sb.append(badKeySet);
sb.append("]");
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();
}
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,14 +27,14 @@ package sun.security.provider.certpath;
import java.io.*;
import java.net.URI;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
import java.util.*;
import sun.security.action.GetBooleanAction;
import sun.security.util.Debug;
import sun.security.util.DerOutputStream;
import static sun.security.x509.PKIXExtensions.*;
import sun.security.x509.*;
/**
@ -57,45 +57,24 @@ class DistributionPointFetcher {
private static final boolean[] ALL_REASONS =
{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 DistributionPointFetcher() {}
/**
* Return a DistributionPointFetcher instance.
*/
static DistributionPointFetcher getInstance() {
return INSTANCE;
}
/**
* Return the X509CRLs matching this selector. The selector must be
* an X509CRLSelector with certificateChecking set.
*
* If CRLDP support is disabled, this method always returns an
* empty set.
*/
Collection<X509CRL> getCRLs(X509CRLSelector selector, boolean signFlag,
PublicKey prevKey, String provider, List<CertStore> certStores,
boolean[] reasonsMask, Set<TrustAnchor> trustAnchors,
Date validity) throws CertStoreException {
if (USE_CRLDP == false) {
return Collections.emptySet();
}
static Collection<X509CRL> getCRLs(X509CRLSelector selector,
boolean signFlag, PublicKey prevKey,
String provider,
List<CertStore> certStores,
boolean[] reasonsMask,
Set<TrustAnchor> trustAnchors,
Date validity)
throws CertStoreException
{
X509Certificate cert = selector.getCertificateChecking();
if (cert == null) {
return Collections.emptySet();
@ -116,7 +95,7 @@ class DistributionPointFetcher {
}
List<DistributionPoint> points =
ext.get(CRLDistributionPointsExtension.POINTS);
Set<X509CRL> results = new HashSet<X509CRL>();
Set<X509CRL> results = new HashSet<>();
for (Iterator<DistributionPoint> t = points.iterator();
t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
DistributionPoint point = t.next();
@ -129,9 +108,7 @@ class DistributionPointFetcher {
debug.println("Returning " + results.size() + " CRLs");
}
return results;
} catch (CertificateException e) {
return Collections.emptySet();
} catch (IOException e) {
} catch (CertificateException | IOException e) {
return Collections.emptySet();
}
}
@ -140,7 +117,7 @@ class DistributionPointFetcher {
* Download CRLs from the given distribution point, verify and return them.
* 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,
boolean signFlag, PublicKey prevKey, String provider,
List<CertStore> certStores, Set<TrustAnchor> trustAnchors,
@ -200,7 +177,7 @@ class DistributionPointFetcher {
certStores, validity)) {
crls.add(crl);
}
} catch (Exception e) {
} catch (IOException | CRLException e) {
// don't add the CRL
if (debug != null) {
debug.println("Exception verifying CRL: " + e.getMessage());
@ -214,7 +191,7 @@ class DistributionPointFetcher {
/**
* Download CRL from given URI.
*/
private X509CRL getCRL(URIName name) {
private static X509CRL getCRL(URIName name) {
URI uri = name.getURI();
if (debug != null) {
debug.println("Trying to fetch CRL from DP " + uri);
@ -240,7 +217,7 @@ class DistributionPointFetcher {
/**
* Fetch CRLs from certStores.
*/
private Collection<X509CRL> getCRLs(X500Name name,
private static Collection<X509CRL> getCRLs(X500Name name,
X500Principal certIssuer, List<CertStore> certStores)
{
if (debug != null) {
@ -249,7 +226,7 @@ class DistributionPointFetcher {
X509CRLSelector xcs = new X509CRLSelector();
xcs.addIssuer(name.asX500Principal());
xcs.addIssuer(certIssuer);
Collection<X509CRL> crls = new ArrayList<X509CRL>();
Collection<X509CRL> crls = new ArrayList<>();
for (CertStore store : certStores) {
try {
for (CRL crl : store.getCRLs(xcs)) {
@ -285,7 +262,7 @@ class DistributionPointFetcher {
* certification path should be determined
* @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,
PublicKey prevKey, String provider,
Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
@ -340,9 +317,9 @@ class DistributionPointFetcher {
} else {
// in case of self-issued indirect CRL issuer.
byte[] certAKID = certImpl.getExtensionValue(
PKIXExtensions.AuthorityKey_Id.toString());
AuthorityKey_Id.toString());
byte[] crlAKID = crlImpl.getExtensionValue(
PKIXExtensions.AuthorityKey_Id.toString());
AuthorityKey_Id.toString());
if (certAKID == null || crlAKID == null) {
// cannot recognize indirect CRL without AKID
@ -539,7 +516,7 @@ class DistributionPointFetcher {
// verify that interim reasons mask includes one or more reasons
// not included in the reasons mask
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]) {
oneOrMore = true;
}
@ -615,7 +592,7 @@ class DistributionPointFetcher {
PKIXCertPathBuilderResult result =
(PKIXCertPathBuilderResult) builder.build(params);
prevKey = result.getPublicKey();
} catch (Exception e) {
} catch (GeneralSecurityException e) {
throw new CRLException(e);
}
}
@ -633,7 +610,7 @@ class DistributionPointFetcher {
// validate the signature on the CRL
try {
crl.verify(prevKey, provider);
} catch (Exception e) {
} catch (GeneralSecurityException e) {
if (debug != null) {
debug.println("CRL signature failed to verify");
}
@ -644,22 +621,21 @@ class DistributionPointFetcher {
Set<String> unresCritExts = crl.getCriticalExtensionOIDs();
// remove any that we have processed
if (unresCritExts != null) {
unresCritExts.remove
(PKIXExtensions.IssuingDistributionPoint_Id.toString());
unresCritExts.remove(IssuingDistributionPoint_Id.toString());
if (!unresCritExts.isEmpty()) {
if (debug != null) {
debug.println("Unrecognized critical extension(s) in CRL: "
+ unresCritExts);
Iterator<String> i = unresCritExts.iterator();
while (i.hasNext())
debug.println(i.next());
for (String ext : unresCritExts) {
debug.println(ext);
}
}
return false;
}
}
// update reasonsMask
for (int i=0; i < interimReasonsMask.length; i++) {
for (int i = 0; i < interimReasonsMask.length; i++) {
if (!reasonsMask[i] && interimReasonsMask[i]) {
reasonsMask[i] = true;
}
@ -671,9 +647,10 @@ class DistributionPointFetcher {
* Append relative name to the issuer name and return a new
* GeneralNames object.
*/
private GeneralNames getFullNames(X500Name issuer, RDN rdn)
throws IOException {
List<RDN> rdns = new ArrayList<RDN>(issuer.rdns());
private static GeneralNames getFullNames(X500Name issuer, RDN rdn)
throws IOException
{
List<RDN> rdns = new ArrayList<>(issuer.rdns());
rdns.add(rdn);
X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));
GeneralNames fullNames = new GeneralNames();
@ -681,15 +658,16 @@ class DistributionPointFetcher {
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 crl the CRL to be verified
* @param provider the name of the signature provider
*/
private static boolean issues(X509CertImpl cert, X509CRLImpl crl,
String provider) throws IOException {
String provider) throws IOException
{
boolean matched = false;
AdaptableX509CertSelector issuerSelector =
@ -727,7 +705,7 @@ class DistributionPointFetcher {
try {
crl.verify(cert.getPublicKey(), provider);
matched = true;
} catch (Exception e) {
} catch (GeneralSecurityException e) {
matched = false;
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,10 +26,9 @@
package sun.security.provider.certpath;
import java.io.IOException;
import java.util.*;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
import java.security.cert.PKIXReason;
@ -40,12 +39,14 @@ import java.security.cert.PKIXCertPathChecker;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.security.cert.X509CertSelector;
import java.util.*;
import javax.security.auth.x500.X500Principal;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
import sun.security.x509.AccessDescription;
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.X500Name;
import sun.security.x509.X509CertImpl;
@ -72,21 +73,17 @@ class ForwardBuilder extends Builder {
TrustAnchor trustAnchor;
private Comparator<X509Certificate> comparator;
private boolean searchAllCertStores = true;
private boolean onlyEECert = false;
/**
* Initialize the builder with the input parameters.
*
* @param params the parameter set used to build a certification path
*/
ForwardBuilder(PKIXBuilderParameters buildParams,
X500Principal targetSubjectDN, boolean searchAllCertStores,
boolean onlyEECert)
{
super(buildParams, targetSubjectDN);
ForwardBuilder(BuilderParams buildParams, boolean searchAllCertStores) {
super(buildParams);
// populate sets of trusted certificates and subject DNs
trustAnchors = buildParams.getTrustAnchors();
trustAnchors = buildParams.trustAnchors();
trustedCerts = new HashSet<X509Certificate>(trustAnchors.size());
trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size());
for (TrustAnchor anchor : trustAnchors) {
@ -100,7 +97,6 @@ class ForwardBuilder extends Builder {
}
comparator = new PKIXCertComparator(trustedSubjectDNs);
this.searchAllCertStores = searchAllCertStores;
this.onlyEECert = onlyEECert;
}
/**
@ -112,8 +108,9 @@ class ForwardBuilder extends Builder {
* Must be an instance of <code>ForwardState</code>
* @param certStores list of CertStores
*/
Collection<X509Certificate> getMatchingCerts
(State currentState, List<CertStore> certStores)
@Override
Collection<X509Certificate> getMatchingCerts(State currentState,
List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException
{
if (debug != null) {
@ -127,7 +124,7 @@ class ForwardBuilder extends Builder {
* As each cert is added, it is sorted based on the PKIXCertComparator
* algorithm.
*/
Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator);
Set<X509Certificate> certs = new TreeSet<>(comparator);
/*
* Only look for EE certs if search has just started.
@ -145,9 +142,10 @@ class ForwardBuilder extends Builder {
* and requirements specified in the parameters and PKIX state.
*/
private void getMatchingEECerts(ForwardState currentState,
List<CertStore> certStores, Collection<X509Certificate> eeCerts)
throws IOException {
List<CertStore> certStores,
Collection<X509Certificate> eeCerts)
throws IOException
{
if (debug != null) {
debug.println("ForwardBuilder.getMatchingEECerts()...");
}
@ -165,12 +163,12 @@ class ForwardBuilder extends Builder {
/*
* Match on certificate validity date
*/
eeSelector.setCertificateValid(date);
eeSelector.setCertificateValid(buildParams.date());
/*
* Policy processing optimizations
*/
if (buildParams.isExplicitPolicyRequired()) {
if (buildParams.explicitPolicyRequired()) {
eeSelector.setPolicy(getMatchingPolicies());
}
/*
@ -188,9 +186,10 @@ class ForwardBuilder extends Builder {
* and requirements specified in the parameters and PKIX state.
*/
private void getMatchingCACerts(ForwardState currentState,
List<CertStore> certStores, Collection<X509Certificate> caCerts)
throws IOException {
List<CertStore> certStores,
Collection<X509Certificate> caCerts)
throws IOException
{
if (debug != null) {
debug.println("ForwardBuilder.getMatchingCACerts()...");
}
@ -216,8 +215,8 @@ class ForwardBuilder extends Builder {
}
if (caTargetSelector == null) {
caTargetSelector = (X509CertSelector)
targetCertConstraints.clone();
caTargetSelector =
(X509CertSelector) targetCertConstraints.clone();
/*
* Since we don't check the validity period of trusted
@ -229,7 +228,7 @@ class ForwardBuilder extends Builder {
/*
* Policy processing optimizations
*/
if (buildParams.isExplicitPolicyRequired())
if (buildParams.explicitPolicyRequired())
caTargetSelector.setPolicy(getMatchingPolicies());
}
@ -249,7 +248,7 @@ class ForwardBuilder extends Builder {
/*
* Policy processing optimizations
*/
if (buildParams.isExplicitPolicyRequired())
if (buildParams.explicitPolicyRequired())
caSelector.setPolicy(getMatchingPolicies());
}
@ -278,7 +277,7 @@ class ForwardBuilder extends Builder {
* check the validity period
*/
caSelector.setValidityPeriod(currentState.cert.getNotBefore(),
currentState.cert.getNotAfter());
currentState.cert.getNotAfter());
sel = caSelector;
}
@ -307,7 +306,7 @@ class ForwardBuilder extends Builder {
* The trusted certificate matching is completed. We need to match
* on certificate validity date.
*/
sel.setCertificateValid(date);
sel.setCertificateValid(buildParams.date());
/*
* Require CA certs with a pathLenConstraint that allows
@ -323,11 +322,12 @@ class ForwardBuilder extends Builder {
* certificate pairs.
*/
if (currentState.isInitial() ||
(buildParams.getMaxPathLength() == -1) ||
(buildParams.getMaxPathLength() > currentState.traversedCACerts))
(buildParams.maxPathLength() == -1) ||
(buildParams.maxPathLength() > currentState.traversedCACerts))
{
if (addMatchingCerts(sel, certStores,
caCerts, searchAllCertStores) && !searchAllCertStores) {
caCerts, searchAllCertStores)
&& !searchAllCertStores) {
return;
}
}
@ -356,7 +356,8 @@ class ForwardBuilder extends Builder {
// because of the selector, so the cast is safe
@SuppressWarnings("unchecked")
private boolean getCerts(AuthorityInfoAccessExtension aiaExt,
Collection<X509Certificate> certs) {
Collection<X509Certificate> certs)
{
if (Builder.USE_AIA == false) {
return false;
}
@ -449,6 +450,7 @@ class ForwardBuilder extends Builder {
* @throws ClassCastException if either argument is not of type
* X509Certificate
*/
@Override
public int compare(X509Certificate oCert1, X509Certificate oCert2) {
// if certs are the same, return 0
@ -651,8 +653,10 @@ class ForwardBuilder extends Builder {
* @param currentState the current state against which the cert is verified
* @param certPathList the certPathList generated thus far
*/
@Override
void verifyCert(X509Certificate cert, State currentState,
List<X509Certificate> certPathList) throws GeneralSecurityException
List<X509Certificate> certPathList)
throws GeneralSecurityException
{
if (debug != null) {
debug.println("ForwardBuilder.verifyCert(SN: "
@ -683,7 +687,7 @@ class ForwardBuilder extends Builder {
debug.println("policyMappingFound = " + policyMappingFound);
}
if (cert.equals(cpListCert)) {
if ((buildParams.isPolicyMappingInhibited()) ||
if ((buildParams.policyMappingInhibited()) ||
(!policyMappingFound)) {
if (debug != null) {
debug.println("loop detected!!");
@ -718,7 +722,7 @@ class ForwardBuilder extends Builder {
* all extensions that all user checkers are capable of
* processing.
*/
for (PKIXCertPathChecker checker : buildParams.getCertPathCheckers()) {
for (PKIXCertPathChecker checker : buildParams.certPathCheckers()) {
if (!checker.isForwardCheckingSupported()) {
Set<String> supportedExts = checker.getSupportedExtensions();
if (supportedExts != null) {
@ -732,23 +736,15 @@ class ForwardBuilder extends Builder {
* to check. If there are any left, throw an exception!
*/
if (!unresCritExts.isEmpty()) {
unresCritExts.remove(
PKIXExtensions.BasicConstraints_Id.toString());
unresCritExts.remove(
PKIXExtensions.NameConstraints_Id.toString());
unresCritExts.remove(
PKIXExtensions.CertificatePolicies_Id.toString());
unresCritExts.remove(
PKIXExtensions.PolicyMappings_Id.toString());
unresCritExts.remove(
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());
unresCritExts.remove(BasicConstraints_Id.toString());
unresCritExts.remove(NameConstraints_Id.toString());
unresCritExts.remove(CertificatePolicies_Id.toString());
unresCritExts.remove(PolicyMappings_Id.toString());
unresCritExts.remove(PolicyConstraints_Id.toString());
unresCritExts.remove(InhibitAnyPolicy_Id.toString());
unresCritExts.remove(SubjectAlternativeName_Id.toString());
unresCritExts.remove(KeyUsage_Id.toString());
unresCritExts.remove(ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty())
throw new CertPathValidatorException
@ -785,32 +781,13 @@ class ForwardBuilder extends Builder {
* 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
* encountered.
*/
if (!currState.keyParamsNeeded()) {
(currState.cert).verify(cert.getPublicKey(),
buildParams.getSigProvider());
buildParams.sigProvider());
}
}
@ -826,6 +803,7 @@ class ForwardBuilder extends Builder {
* @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path.
*/
@Override
boolean isPathCompleted(X509Certificate cert) {
for (TrustAnchor anchor : trustAnchors) {
if (anchor.getTrustedCert() != null) {
@ -837,7 +815,7 @@ class ForwardBuilder extends Builder {
}
} else {
X500Principal principal = anchor.getCA();
java.security.PublicKey publicKey = anchor.getCAPublicKey();
PublicKey publicKey = anchor.getCAPublicKey();
if (principal != null && publicKey != null &&
principal.equals(cert.getSubjectX500Principal())) {
@ -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
*/
@ -879,18 +842,17 @@ class ForwardBuilder extends Builder {
// parameters, yet there is no key to inherit the parameters
// from. This is probably such a rare case that it is not worth
// trying to detect the situation earlier.
cert.verify(anchor.getCAPublicKey(),
buildParams.getSigProvider());
cert.verify(anchor.getCAPublicKey(), buildParams.sigProvider());
} catch (InvalidKeyException ike) {
if (debug != null) {
debug.println("ForwardBuilder.isPathCompleted() invalid "
+ "DSA key found");
+ "DSA key found");
}
continue;
} catch (Exception e){
} catch (GeneralSecurityException e){
if (debug != null) {
debug.println("ForwardBuilder.isPathCompleted() " +
"unexpected exception");
"unexpected exception");
e.printStackTrace();
}
continue;
@ -908,8 +870,10 @@ class ForwardBuilder extends Builder {
* @param cert the certificate to be added
* @param certPathList the certification path list
*/
@Override
void addCertToPath(X509Certificate cert,
LinkedList<X509Certificate> certPathList) {
LinkedList<X509Certificate> certPathList)
{
certPathList.addFirst(cert);
}
@ -917,6 +881,7 @@ class ForwardBuilder extends Builder {
*
* @param certPathList the certification path list
*/
@Override
void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
certPathList.removeFirst();
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -34,7 +34,6 @@ import java.security.cert.X509Certificate;
import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.security.auth.x500.X500Principal;
@ -76,9 +75,6 @@ class ForwardState implements State {
/* Flag indicating if state is initial (path is just starting) */
private boolean init = true;
/* the checker used for revocation status */
public CrlRevocationChecker crlChecker;
/* The list of user-defined checkers that support forward checking */
ArrayList<PKIXCertPathChecker> forwardCheckers;
@ -93,6 +89,7 @@ class ForwardState implements State {
*
* @return boolean flag indicating if the state is initial (just starting)
*/
@Override
public boolean isInitial() {
return init;
}
@ -104,6 +101,7 @@ class ForwardState implements State {
* @return boolean true if key needing to inherit parameters has been
* encountered; false otherwise.
*/
@Override
public boolean keyParamsNeeded() {
return keyParamsNeededFlag;
}
@ -111,23 +109,18 @@ class ForwardState implements State {
/**
* Display state for debugging purposes
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
try {
sb.append("State [");
sb.append("\n issuerDN of last cert: " + issuerDN);
sb.append("\n traversedCACerts: " + traversedCACerts);
sb.append("\n init: " + String.valueOf(init));
sb.append("\n keyParamsNeeded: "
+ String.valueOf(keyParamsNeededFlag));
sb.append("\n subjectNamesTraversed: \n" + subjectNamesTraversed);
sb.append("]\n");
} catch (Exception e) {
if (debug != null) {
debug.println("ForwardState.toString() unexpected exception");
e.printStackTrace();
}
}
StringBuilder sb = new StringBuilder();
sb.append("State [");
sb.append("\n issuerDN of last cert: ").append(issuerDN);
sb.append("\n traversedCACerts: ").append(traversedCACerts);
sb.append("\n init: ").append(String.valueOf(init));
sb.append("\n keyParamsNeeded: ").append
(String.valueOf(keyParamsNeededFlag));
sb.append("\n subjectNamesTraversed: \n").append
(subjectNamesTraversed);
sb.append("]\n");
return sb.toString();
}
@ -147,12 +140,10 @@ class ForwardState implements State {
* that supports forward checking and initialize the forwardCheckers
*/
forwardCheckers = new ArrayList<PKIXCertPathChecker>();
if (certPathCheckers != null) {
for (PKIXCertPathChecker checker : certPathCheckers) {
if (checker.isForwardCheckingSupported()) {
checker.init(true);
forwardCheckers.add(checker);
}
for (PKIXCertPathChecker checker : certPathCheckers) {
if (checker.isForwardCheckingSupported()) {
checker.init(true);
forwardCheckers.add(checker);
}
}
@ -164,6 +155,7 @@ class ForwardState implements State {
*
* @param cert the certificate which is used to update the state
*/
@Override
public void updateState(X509Certificate cert)
throws CertificateException, IOException, CertPathValidatorException {
@ -208,13 +200,11 @@ class ForwardState implements State {
if (subjAltNameExt != null) {
GeneralNames gNames = subjAltNameExt.get(
SubjectAlternativeNameExtension.SUBJECT_NAME);
for (Iterator<GeneralName> t = gNames.iterator();
t.hasNext(); ) {
GeneralNameInterface gName = t.next().getName();
subjectNamesTraversed.add(gName);
for (GeneralName gName : gNames.names()) {
subjectNamesTraversed.add(gName.getName());
}
}
} catch (Exception e) {
} catch (IOException e) {
if (debug != null) {
debug.println("ForwardState.updateState() unexpected "
+ "exception");
@ -236,6 +226,7 @@ class ForwardState implements State {
* because some of them will
* not have their contents modified by subsequent calls to updateState.
*/
@Override
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
public Object clone() {
try {

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -180,7 +180,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
if (cert.equals(oldEntry)) {
return;
}
List<X509Certificate> list = new ArrayList<X509Certificate>(2);
List<X509Certificate> list = new ArrayList<>(2);
list.add(cert);
list.add((X509Certificate)oldEntry);
certSubjects.put(subject, list);
@ -206,7 +206,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
if (crl.equals(oldEntry)) {
return;
}
List<X509CRL> list = new ArrayList<X509CRL>(2);
List<X509CRL> list = new ArrayList<>(2);
list.add(crl);
list.add((X509CRL)oldEntry);
crlIssuers.put(issuer, list);
@ -234,19 +234,20 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
@Override
public Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
throws CertStoreException {
// no selector means match all
if (selector == null) {
Set<Certificate> matches = new HashSet<Certificate>();
Set<Certificate> matches = new HashSet<>();
matchX509Certs(new X509CertSelector(), matches);
matches.addAll(otherCertificates);
return matches;
}
if (selector instanceof X509CertSelector == false) {
Set<Certificate> matches = new HashSet<Certificate>();
Set<Certificate> matches = new HashSet<>();
matchX509Certs(selector, matches);
for (Certificate cert : otherCertificates) {
if (selector.match(cert)) {
@ -285,7 +286,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
// See certSubjects javadoc.
@SuppressWarnings("unchecked")
List<X509Certificate> list = (List<X509Certificate>)entry;
Set<X509Certificate> matches = new HashSet<X509Certificate>(16);
Set<X509Certificate> matches = new HashSet<>(16);
for (X509Certificate cert : list) {
if (x509Selector.match(cert)) {
matches.add(cert);
@ -295,7 +296,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
}
}
// cannot use index, iterate all
Set<Certificate> matches = new HashSet<Certificate>(16);
Set<Certificate> matches = new HashSet<>(16);
matchX509Certs(x509Selector, matches);
return matches;
}
@ -338,18 +339,19 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
@Override
public Collection<CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException {
if (selector == null) {
Set<CRL> matches = new HashSet<CRL>();
Set<CRL> matches = new HashSet<>();
matchX509CRLs(new X509CRLSelector(), matches);
matches.addAll(otherCRLs);
return matches;
}
if (selector instanceof X509CRLSelector == false) {
Set<CRL> matches = new HashSet<CRL>();
Set<CRL> matches = new HashSet<>();
matchX509CRLs(selector, matches);
for (CRL crl : otherCRLs) {
if (selector.match(crl)) {
@ -366,7 +368,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
// see if the issuer is specified
Collection<X500Principal> issuers = x509Selector.getIssuers();
if (issuers != null) {
HashSet<CRL> matches = new HashSet<CRL>(16);
HashSet<CRL> matches = new HashSet<>(16);
for (X500Principal issuer : issuers) {
Object entry = crlIssuers.get(issuer);
if (entry == null) {
@ -390,7 +392,7 @@ public class IndexedCollectionCertStore extends CertStoreSpi {
return matches;
}
// cannot use index, iterate all
Set<CRL> matches = new HashSet<CRL>(16);
Set<CRL> matches = new HashSet<>(16);
matchX509CRLs(x509Selector, matches);
return matches;
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,7 +30,7 @@ import java.security.cert.*;
import java.security.cert.PKIXReason;
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
@ -45,33 +45,29 @@ import sun.security.x509.PKIXExtensions;
class KeyChecker extends PKIXCertPathChecker {
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 CertSelector targetConstraints;
private final CertSelector targetConstraints;
private int remainingCerts;
private Set<String> supportedExts;
/**
* Default Constructor
* Creates a KeyChecker.
*
* @param certPathLen allowable cert path length
* @param targetCertSel a CertSelector object specifying the constraints
* on the target certificate
*/
KeyChecker(int certPathLen, CertSelector targetCertSel)
throws CertPathValidatorException
{
KeyChecker(int certPathLen, CertSelector targetCertSel) {
this.certPathLen = certPathLen;
this.targetConstraints = targetCertSel;
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 = certPathLen;
@ -81,16 +77,18 @@ class KeyChecker extends PKIXCertPathChecker {
}
}
public final boolean isForwardCheckingSupported() {
@Override
public boolean isForwardCheckingSupported() {
return false;
}
@Override
public Set<String> getSupportedExtensions() {
if (supportedExts == null) {
supportedExts = new HashSet<String>();
supportedExts.add(PKIXExtensions.KeyUsage_Id.toString());
supportedExts.add(PKIXExtensions.ExtendedKeyUsage_Id.toString());
supportedExts.add(PKIXExtensions.SubjectAlternativeName_Id.toString());
supportedExts = new HashSet<String>(3);
supportedExts.add(KeyUsage_Id.toString());
supportedExts.add(ExtendedKeyUsage_Id.toString());
supportedExts.add(SubjectAlternativeName_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts);
}
return supportedExts;
@ -102,20 +100,20 @@ class KeyChecker extends PKIXCertPathChecker {
*
* @param cert the Certificate
* @param unresolvedCritExts the unresolved critical extensions
* @exception CertPathValidatorException Exception thrown if certificate
* does not verify
* @throws CertPathValidatorException if certificate does not verify
*/
@Override
public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException
{
X509Certificate currCert = (X509Certificate) cert;
X509Certificate currCert = (X509Certificate)cert;
remainingCerts--;
// if final certificate, check that target constraints are satisfied
if (remainingCerts == 0) {
if ((targetConstraints != null) &&
(targetConstraints.match(currCert) == false)) {
if (targetConstraints != null &&
targetConstraints.match(currCert) == false) {
throw new CertPathValidatorException("target certificate " +
"constraints check failed");
}
@ -126,25 +124,26 @@ class KeyChecker extends PKIXCertPathChecker {
// remove the extensions that we have checked
if (unresCritExts != null && !unresCritExts.isEmpty()) {
unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
unresCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString());
unresCritExts.remove(
PKIXExtensions.SubjectAlternativeName_Id.toString());
unresCritExts.remove(KeyUsage_Id.toString());
unresCritExts.remove(ExtendedKeyUsage_Id.toString());
unresCritExts.remove(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
* extension in a CA cert. The key usage extension, if present, must
* assert the keyCertSign bit. The extended key usage extension, if
* present, must include anyExtendedKeyUsage.
* Verifies the key usage extension in a CA cert.
* The key usage extension, if present, must assert the keyCertSign bit.
* The extended key usage extension is not checked (see CR 4776794 for
* more information).
*/
static void verifyCAKeyUsage(X509Certificate cert)
throws CertPathValidatorException {
String msg = "CA key usage";
if (debug != null) {
debug.println("KeyChecker.verifyCAKeyUsage() ---checking " + msg
+ "...");
+ "...");
}
boolean[] keyUsageBits = cert.getKeyUsage();
@ -156,7 +155,7 @@ class KeyChecker extends PKIXCertPathChecker {
}
// throw an exception if the keyCertSign bit is not set
if (!keyUsageBits[keyCertSign]) {
if (!keyUsageBits[KEY_CERT_SIGN]) {
throw new CertPathValidatorException
(msg + " check failed: keyCertSign bit is not set", null,
null, -1, PKIXReason.INVALID_KEY_USAGE);
@ -164,7 +163,7 @@ class KeyChecker extends PKIXCertPathChecker {
if (debug != null) {
debug.println("KeyChecker.verifyCAKeyUsage() " + msg
+ " verified.");
+ " verified.");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,6 +43,7 @@ import java.util.Map;
import static sun.security.provider.certpath.OCSPResponse.*;
import sun.security.util.Debug;
import sun.security.util.ObjectIdentifier;
import sun.security.x509.AccessDescription;
import sun.security.x509.AuthorityInfoAccessExtension;
import sun.security.x509.GeneralName;
@ -62,6 +63,9 @@ import sun.security.x509.X509CertImpl;
*/
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 int CONNECT_TIMEOUT = 15000; // 15 seconds
@ -83,7 +87,7 @@ public final class OCSP {
* encoding the OCSP Request or validating the OCSP Response
*/
public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert)
X509Certificate issuerCert)
throws IOException, CertPathValidatorException {
CertId certId = null;
URI responderURI = null;
@ -95,16 +99,13 @@ public final class OCSP {
("No OCSP Responder URI in certificate");
}
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
("Exception while encoding OCSPRequest", ioe);
("Exception while encoding OCSPRequest", e);
}
OCSPResponse ocspResponse = check(Collections.singletonList(certId),
responderURI, issuerCert, null);
return (RevocationStatus) ocspResponse.getSingleResponse(certId);
responderURI, issuerCert, null, Collections.<Extension>emptyList());
return (RevocationStatus)ocspResponse.getSingleResponse(certId);
}
/**
@ -123,22 +124,34 @@ public final class OCSP {
* encoding the OCSP Request or validating the OCSP Response
*/
public static RevocationStatus check(X509Certificate cert,
X509Certificate issuerCert, URI responderURI, X509Certificate
responderCert, Date date)
throws IOException, CertPathValidatorException {
X509Certificate issuerCert,
URI responderURI,
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;
try {
X509CertImpl certImpl = X509CertImpl.toImpl(cert);
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
("Exception while encoding OCSPRequest", ioe);
("Exception while encoding OCSPRequest", e);
}
OCSPResponse ocspResponse = check(Collections.singletonList(certId),
responderURI, responderCert, date);
responderURI, responderCert, date, extensions);
return (RevocationStatus) ocspResponse.getSingleResponse(certId);
}
@ -157,12 +170,14 @@ public final class OCSP {
* encoding the OCSP Request or validating the OCSP Response
*/
static OCSPResponse check(List<CertId> certIds, URI responderURI,
X509Certificate responderCert, Date date)
throws IOException, CertPathValidatorException {
X509Certificate responderCert, Date date,
List<Extension> extensions)
throws IOException, CertPathValidatorException
{
byte[] bytes = null;
OCSPRequest request = null;
try {
OCSPRequest request = new OCSPRequest(certIds);
request = new OCSPRequest(certIds, extensions);
bytes = request.encodeBytes();
} catch (IOException ioe) {
throw new CertPathValidatorException
@ -214,6 +229,8 @@ public final class OCSP {
}
}
response = Arrays.copyOf(response, total);
} catch (IOException ioe) {
throw new NetworkFailureException(ioe);
} finally {
if (in != null) {
try {
@ -233,33 +250,15 @@ public final class OCSP {
OCSPResponse ocspResponse = null;
try {
ocspResponse = new OCSPResponse(response, date, responderCert);
ocspResponse = new OCSPResponse(response);
} catch (IOException ioe) {
// response decoding exception
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
// certs that were supplied in the request
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());
}
}
// verify the response
ocspResponse.verify(certIds, responderCert, date, request.getNonce());
return ocspResponse;
}
@ -271,6 +270,7 @@ public final class OCSP {
* @param cert the certificate
* @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) {
try {
return getResponderURI(X509CertImpl.toImpl(cert));
@ -330,4 +330,12 @@ public final class OCSP {
*/
Map<String, Extension> getSingleExtensions();
}
static class NetworkFailureException extends CertPathValidatorException {
private static final long serialVersionUID = 0l;
private NetworkFailureException(IOException ioe) {
super(ioe);
}
}
}

View File

@ -1,446 +0,0 @@
/*
* 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();
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,8 +26,10 @@
package sun.security.provider.certpath;
import java.io.IOException;
import java.security.cert.Extension;
import java.util.Collections;
import java.util.List;
import sun.misc.HexDumpEncoder;
import sun.security.util.*;
@ -74,22 +76,29 @@ import sun.security.util.*;
class OCSPRequest {
private static final Debug debug = Debug.getInstance("certpath");
private static final boolean dump = false;
// List of request CertIds
private final List<CertId> certIds;
private final List<Extension> extensions;
private byte[] nonce;
/*
* Constructs an OCSPRequest. This constructor is used
* to construct an unsigned OCSP Request for a single user cert.
*/
OCSPRequest(CertId certId) {
this.certIds = Collections.singletonList(certId);
this(Collections.singletonList(certId));
}
OCSPRequest(List<CertId> 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 {
@ -104,7 +113,20 @@ class OCSPRequest {
}
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();
tbsRequest.write(DerValue.tag_Sequence, tmp);
@ -126,4 +148,8 @@ class OCSPRequest {
List<CertId> getCertIds() {
return certIds;
}
byte[] getNonce() {
return nonce;
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,11 +33,15 @@ import java.security.cert.CertPathValidatorException;
import java.security.cert.CRLReason;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.security.auth.x500.X500Principal;
import sun.misc.HexDumpEncoder;
import sun.security.x509.*;
import sun.security.util.*;
@ -125,13 +129,10 @@ public final class OCSPResponse {
};
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 ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
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_REVOKED = 1;
private static final int CERT_STATUS_UNKNOWN = 2;
@ -143,9 +144,6 @@ public final class OCSPResponse {
// 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 final ResponseStatus responseStatus;
private final Map<CertId, SingleResponse> singleResponseMap;
// Maximum clock skew in milliseconds (15 minutes) allowed when checking
// validity of OCSP responses
private static final long MAX_CLOCK_SKEW = 900000;
@ -153,14 +151,20 @@ public final class OCSPResponse {
// an array of all of the CRLReasons (used in SingleResponse)
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.
*/
OCSPResponse(byte[] bytes, Date dateCheckedAgainst,
X509Certificate responderCert)
throws IOException, CertPathValidatorException {
// OCSPResponse
OCSPResponse(byte[] bytes) throws IOException {
if (dump) {
HexDumpEncoder hexEnc = new HexDumpEncoder();
System.out.println("OCSPResponse bytes are...");
@ -181,12 +185,19 @@ public final class OCSPResponse {
// unspecified responseStatus
throw new IOException("Unknown OCSPResponse status: " + status);
}
if (DEBUG != null) {
DEBUG.println("OCSP response status: " + responseStatus);
if (debug != null) {
debug.println("OCSP response status: " + responseStatus);
}
if (responseStatus != ResponseStatus.SUCCESSFUL) {
// no need to continue, responseBytes are not set.
singleResponseMap = Collections.emptyMap();
certs = Collections.<X509CertImpl>emptyList();
sigAlgId = null;
signature = null;
tbsResponseData = null;
responderName = null;
responderKey = null;
responseNonce = null;
return;
}
@ -206,15 +217,15 @@ public final class OCSPResponse {
derIn = tmp.data;
ObjectIdentifier responseType = derIn.getOID();
if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) {
if (DEBUG != null) {
DEBUG.println("OCSP response type: basic");
if (debug != null) {
debug.println("OCSP response type: basic");
}
} else {
if (DEBUG != null) {
DEBUG.println("OCSP response type: " + responseType);
if (debug != null) {
debug.println("OCSP response type: " + responseType);
}
throw new IOException("Unsupported OCSP response type: " +
responseType);
responseType);
}
// BasicOCSPResponse
@ -229,7 +240,7 @@ public final class OCSPResponse {
DerValue responseData = seqTmp[0];
// Need the DER encoded ResponseData to verify the signature later
byte[] responseDataDer = seqTmp[0].toByteArray();
tbsResponseData = seqTmp[0].toByteArray();
// tbsResponseData
if (responseData.tag != DerValue.tag_Sequence) {
@ -257,12 +268,15 @@ public final class OCSPResponse {
// responderID
short tag = (byte)(seq.tag & 0x1f);
if (tag == NAME_TAG) {
if (DEBUG != null) {
X500Name responderName = new X500Name(seq.getData());
DEBUG.println("OCSP Responder name: " + responderName);
responderName =
new X500Principal(new ByteArrayInputStream(seq.toByteArray()));
if (debug != null) {
debug.println("OCSP Responder name: " + responderName);
}
responderKey = null;
} else if (tag == KEY_TAG) {
// Ignore, for now
responderKey = seq.getOctetString();
responderName = null;
} else {
throw new IOException("Bad encoding in responderID element of " +
"OCSP response: expected ASN.1 context specific tag 0 or 1");
@ -270,57 +284,55 @@ public final class OCSPResponse {
// producedAt
seq = seqDerIn.getDerValue();
if (DEBUG != null) {
if (debug != null) {
Date producedAtDate = seq.getGeneralizedTime();
DEBUG.println("OCSP response produced at: " + producedAtDate);
debug.println("OCSP response produced at: " + producedAtDate);
}
// responses
DerValue[] singleResponseDer = seqDerIn.getSequence(1);
singleResponseMap
= new HashMap<CertId, SingleResponse>(singleResponseDer.length);
if (DEBUG != null) {
DEBUG.println("OCSP number of SingleResponses: "
+ singleResponseDer.length);
singleResponseMap = new HashMap<>(singleResponseDer.length);
if (debug != null) {
debug.println("OCSP number of SingleResponses: "
+ singleResponseDer.length);
}
for (int i = 0; i < singleResponseDer.length; i++) {
SingleResponse singleResponse
= new SingleResponse(singleResponseDer[i]);
SingleResponse singleResponse =
new SingleResponse(singleResponseDer[i]);
singleResponseMap.put(singleResponse.getCertId(), singleResponse);
}
// responseExtensions
byte[] nonce = null;
if (seqDerIn.available() > 0) {
seq = seqDerIn.getDerValue();
if (seq.isContextSpecific((byte)1)) {
DerValue[] responseExtDer = seq.data.getSequence(3);
for (int i = 0; i < responseExtDer.length; i++) {
Extension responseExtension
= new Extension(responseExtDer[i]);
if (DEBUG != null) {
DEBUG.println("OCSP extension: " + responseExtension);
Extension ext = new Extension(responseExtDer[i]);
if (debug != null) {
debug.println("OCSP extension: " + ext);
}
if (responseExtension.getExtensionId().equals((Object)
OCSP_NONCE_EXTENSION_OID)) {
/*
ocspNonce =
responseExtension[i].getExtensionValue();
*/
} else if (responseExtension.isCritical()) {
// Only the NONCE extension is recognized
if (ext.getExtensionId().equals((Object)
OCSP.NONCE_EXTENSION_OID))
{
nonce = ext.getExtensionValue();
} else if (ext.isCritical()) {
throw new IOException(
"Unsupported OCSP critical extension: " +
responseExtension.getExtensionId());
ext.getExtensionId());
}
}
}
}
responseNonce = nonce;
// signatureAlgorithmId
AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]);
sigAlgId = AlgorithmId.parse(seqTmp[1]);
// signature
byte[] signature = seqTmp[2].getBitString();
X509CertImpl[] x509Certs = null;
signature = seqTmp[2].getBitString();
// if seq[3] is available , then it is a sequence of certificates
if (seqTmp.length > 3) {
@ -330,30 +342,59 @@ public final class OCSPResponse {
throw new IOException("Bad encoding in certs element of " +
"OCSP response: expected ASN.1 context specific tag 0.");
}
DerValue[] certs = seqCert.getData().getSequence(3);
x509Certs = new X509CertImpl[certs.length];
DerValue[] derCerts = seqCert.getData().getSequence(3);
certs = new ArrayList<X509CertImpl>(derCerts.length);
try {
for (int i = 0; i < certs.length; i++) {
x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
for (int i = 0; i < derCerts.length; i++) {
certs.add(new X509CertImpl(derCerts[i].toByteArray()));
}
} catch (CertificateException 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 whether the cert returned by the responder is trusted
if (x509Certs != null && x509Certs[0] != null) {
X509CertImpl cert = x509Certs[0];
// 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());
}
}
// First check if the cert matches the responder cert which
// was set locally.
// Check whether the cert returned by the responder is trusted
if (!certs.isEmpty()) {
X509CertImpl cert = certs.get(0);
// First check if the cert matches the expected responder cert
if (cert.equals(responderCert)) {
// cert is trusted, now verify the signed response
// Next check if the cert was issued by the responder cert
// which was set locally.
} else if (cert.getIssuerX500Principal().equals(
responderCert.getSubjectX500Principal())) {
responderCert.getSubjectX500Principal())) {
// Check for the OCSPSigning key purpose
try {
@ -380,12 +421,12 @@ public final class OCSPResponse {
// check the validity
try {
if (dateCheckedAgainst == null) {
if (date == null) {
cert.checkValidity();
} else {
cert.checkValidity(dateCheckedAgainst);
cert.checkValidity(date);
}
} catch (GeneralSecurityException e) {
} catch (CertificateException e) {
throw new CertPathValidatorException(
"Responder's certificate not within the " +
"validity period", e);
@ -401,8 +442,8 @@ public final class OCSPResponse {
Extension noCheck =
cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
if (noCheck != null) {
if (DEBUG != null) {
DEBUG.println("Responder's certificate includes " +
if (debug != null) {
debug.println("Responder's certificate includes " +
"the extension id-pkix-ocsp-nocheck.");
}
} else {
@ -433,15 +474,44 @@ public final class OCSPResponse {
// "jdk.certpath.disabledAlgorithms".
AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
if (!verifyResponse(responseDataDer, responderCert,
sigAlgId, signature)) {
if (!verifySignature(responderCert)) {
throw new CertPathValidatorException(
"Error verifying OCSP Responder's signature");
"Error verifying OCSP Response's signature");
}
} else {
// Need responder's cert in order to verify the signature
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 {
* Verify the signature of the OCSP response.
* The responder's cert is implicitly trusted.
*/
private boolean verifyResponse(byte[] responseData, X509Certificate cert,
AlgorithmId sigAlgId, byte[] signBytes)
private boolean verifySignature(X509Certificate cert)
throws CertPathValidatorException {
try {
Signature respSignature = Signature.getInstance(sigAlgId.getName());
respSignature.initVerify(cert);
respSignature.update(responseData);
respSignature.update(tbsResponseData);
if (respSignature.verify(signBytes)) {
if (DEBUG != null) {
DEBUG.println("Verified signature of OCSP Responder");
if (respSignature.verify(signature)) {
if (debug != null) {
debug.println("Verified signature of OCSP Response");
}
return true;
} else {
if (DEBUG != null) {
DEBUG.println(
"Error verifying signature of OCSP Responder");
if (debug != null) {
debug.println(
"Error verifying signature of OCSP Response");
}
return false;
}
} catch (InvalidKeyException ike) {
throw new CertPathValidatorException(ike);
} catch (NoSuchAlgorithmException nsae) {
throw new CertPathValidatorException(nsae);
} catch (SignatureException se) {
throw new CertPathValidatorException(se);
} catch (InvalidKeyException | NoSuchAlgorithmException |
SignatureException e)
{
throw new CertPathValidatorException(e);
}
}
@ -537,9 +604,9 @@ public final class OCSPResponse {
revocationReason = CRLReason.UNSPECIFIED;
}
// RevokedInfo
if (DEBUG != null) {
DEBUG.println("Revocation time: " + revocationTime);
DEBUG.println("Revocation reason: " + revocationReason);
if (debug != null) {
debug.println("Revocation time: " + revocationTime);
debug.println("Revocation reason: " + revocationReason);
}
} else {
revocationTime = null;
@ -585,8 +652,8 @@ public final class OCSPResponse {
(singleExtDer.length);
for (int i = 0; i < singleExtDer.length; i++) {
Extension ext = new Extension(singleExtDer[i]);
if (DEBUG != null) {
DEBUG.println("OCSP single extension: " + ext);
if (debug != null) {
debug.println("OCSP single extension: " + ext);
}
// We don't support any extensions yet. Therefore, if it
// is critical we must throw an exception because we
@ -604,29 +671,6 @@ public final class OCSPResponse {
} else {
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");
}
}
/*

View File

@ -0,0 +1,289 @@
/*
* 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;
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,55 +25,38 @@
package sun.security.provider.certpath;
import java.security.AccessController;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.cert.CertPath;
import java.security.cert.CertPathParameters;
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 java.security.cert.*;
import java.util.*;
import sun.security.provider.certpath.PKIX.ValidatorParams;
import sun.security.x509.X509CertImpl;
import sun.security.util.Debug;
/**
* This class implements the PKIX validation algorithm for certification
* paths consisting exclusively of <code>X509Certificates</code>. It uses
* 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
* @author Yassir Elley
*/
public class PKIXCertPathValidator extends CertPathValidatorSpi {
public final class PKIXCertPathValidator extends CertPathValidatorSpi {
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.
*/
public PKIXCertPathValidator() {}
@Override
public CertPathChecker engineGetRevocationChecker() {
return new RevocationChecker();
}
/**
* Validates a certification path consisting exclusively of
* <code>X509Certificate</code>s using the PKIX validation algorithm,
@ -81,98 +64,70 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
* The input parameter set must be a <code>PKIXParameters</code> object.
*
* @param cp the X509 certification path
* @param param the input PKIX parameter set
* @param params the input PKIX parameter set
* @return the result
* @exception CertPathValidatorException Exception thrown if cert path
* does not validate.
* @exception InvalidAlgorithmParameterException if the specified
* parameters are inappropriate for this certification path validator
* @throws CertPathValidatorException if cert path does not validate.
* @throws InvalidAlgorithmParameterException if the specified
* parameters are inappropriate for this CertPathValidator
*/
@Override
public CertPathValidatorResult engineValidate(CertPath cp,
CertPathParameters param)
CertPathParameters params)
throws CertPathValidatorException, InvalidAlgorithmParameterException
{
ValidatorParams valParams = PKIX.checkParams(cp, params);
return validate(valParams);
}
private static PKIXCertPathValidatorResult validate(ValidatorParams params)
throws CertPathValidatorException
{
if (debug != null)
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
// (to be used later in pre-screening)
X509Certificate firstCert = null;
AdaptableX509CertSelector selector = null;
List<X509Certificate> certList = params.certificates();
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;
// We iterate through the set of trust anchors until we find
// one that works at which time we stop iterating
for (TrustAnchor anchor : anchors) {
for (TrustAnchor anchor : params.trustAnchors()) {
X509Certificate trustedCert = anchor.getTrustedCert();
if (trustedCert != null) {
if (debug != null) {
debug.println("PKIXCertPathValidator.engineValidate() "
+ "anchor.getTrustedCert() != null");
}
// if this trust anchor is not worth trying,
// 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;
}
if (debug != null) {
debug.println("YES - try this trustedCert");
debug.println("anchor.getTrustedCert()."
+ "getSubjectX500Principal() = "
+ trustedCert.getSubjectX500Principal());
@ -185,14 +140,7 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
}
try {
PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
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());
return validate(anchor, params);
} catch (CertPathValidatorException cpe) {
// remember this exception
lastException = cpe;
@ -210,144 +158,59 @@ public class PKIXCertPathValidator extends CertPathValidatorSpi {
null, null, -1, PKIXReason.NO_TRUST_ANCHOR);
}
/**
* Internal method to do some simple checks to see if a given cert is
* worth trying to validate in the chain.
*/
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)
private static PKIXCertPathValidatorResult validate(TrustAnchor anchor,
ValidatorParams params)
throws CertPathValidatorException
{
// default value for testDate is current time
testDate = pkixParam.getDate();
if (testDate == null) {
testDate = new Date(System.currentTimeMillis());
}
int certPathLen = params.certificates().size();
userCheckers = pkixParam.getCertPathCheckers();
sigProvider = pkixParam.getSigProvider();
if (pkixParam.isRevocationEnabled()) {
// Examine OCSP security property
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>();
// create PKIXCertPathCheckers
List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
// add standard checkers that we will be using
certPathCheckers.add(algorithmChecker);
certPathCheckers.add(keyChecker);
certPathCheckers.add(constraintsChecker);
certPathCheckers.add(policyChecker);
certPathCheckers.add(basicChecker);
certPathCheckers.add(new AlgorithmChecker(anchor));
certPathCheckers.add(new KeyChecker(certPathLen,
params.targetCertConstraints()));
certPathCheckers.add(new ConstraintsChecker(certPathLen));
PolicyNodeImpl rootNode =
new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, false,
Collections.singleton(PolicyChecker.ANY_POLICY),
false);
PolicyChecker pc = new PolicyChecker(params.initialPolicies(),
certPathLen,
params.explicitPolicyRequired(),
params.policyMappingInhibited(),
params.anyPolicyInhibited(),
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);
// only add a revocationChecker if revocation is enabled
if (pkixParam.isRevocationEnabled()) {
// Use OCSP if it has been enabled
if (ocspEnabled) {
OCSPChecker ocspChecker =
new OCSPChecker(cpOriginal, pkixParam, onlyEECert);
certPathCheckers.add(ocspChecker);
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
certPathCheckers.addAll(userCheckers);
certPathCheckers.addAll(checkers);
PKIXMasterCertPathValidator masterValidator =
new PKIXMasterCertPathValidator(certPathCheckers);
PKIXMasterCertPathValidator.validate(params.certPath(),
params.certificates(),
certPathCheckers);
masterValidator.validate(cpOriginal, certList);
return policyChecker.getPolicyTree();
return new PKIXCertPathValidatorResult(anchor, pc.getPolicyTree(),
bc.getPublicKey());
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -30,10 +30,8 @@ import sun.security.util.Debug;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.security.cert.CertificateRevokedException;
import java.security.cert.CertPath;
import java.security.cert.CertPathValidatorException;
import java.security.cert.CertPathValidatorException.BasicReason;
import java.security.cert.PKIXCertPathChecker;
import java.security.cert.PKIXReason;
import java.security.cert.X509Certificate;
@ -49,32 +47,22 @@ import java.security.cert.X509Certificate;
class PKIXMasterCertPathValidator {
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
* <code>X509Certificate</code>s using the
* <code>PKIXCertPathChecker</code>s specified
* in the constructor. It is assumed that the
* <code>X509Certificate</code>s using the specified
* <code>PKIXCertPathChecker</code>s. It is assumed that the
* <code>PKIXCertPathChecker</code>s
* have been initialized with any input parameters they may need.
*
* @param cpOriginal the original X509 CertPath passed in by the user
* @param reversedCertList the reversed X509 CertPath (as a List)
* @exception CertPathValidatorException Exception thrown if cert
* path does not validate.
* @param certPathCheckers the PKIXCertPathCheckers
* @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
{
// we actually process reversedCertList, but we keep cpOriginal because
@ -104,20 +92,18 @@ class PKIXMasterCertPathValidator {
debug.println("Checking cert" + (i+1) + " ...");
X509Certificate currCert = reversedCertList.get(i);
Set<String> unresolvedCritExts =
currCert.getCriticalExtensionOIDs();
if (unresolvedCritExts == null) {
unresolvedCritExts = Collections.<String>emptySet();
Set<String> unresCritExts = currCert.getCriticalExtensionOIDs();
if (unresCritExts == null) {
unresCritExts = Collections.<String>emptySet();
}
if (debug != null && !unresolvedCritExts.isEmpty()) {
if (debug != null && !unresCritExts.isEmpty()) {
debug.println("Set of critical extensions:");
for (String oid : unresolvedCritExts) {
for (String oid : unresCritExts) {
debug.println(oid);
}
}
CertPathValidatorException ocspCause = null;
for (int j = 0; j < certPathCheckers.size(); j++) {
PKIXCertPathChecker currChecker = certPathCheckers.get(j);
@ -130,65 +116,21 @@ class PKIXMasterCertPathValidator {
currChecker.init(false);
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
if (debug != null) {
debug.println("-checker" + (j + 1) +
" validation succeeded");
}
} 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) {
debug.println(cpve.getMessage());
debug.println(
"preparing to failover (from OCSP to CRLs)");
}
throw new CertPathValidatorException(cpve.getMessage(),
cpve.getCause(), cpOriginal, cpSize - (i + 1),
cpve.getReason());
}
if (debug != null)
debug.println("-checker" + (j+1) + " validation succeeded");
}
if (debug != null)
debug.println("checking for unresolvedCritExts");
if (!unresolvedCritExts.isEmpty()) {
if (!unresCritExts.isEmpty()) {
throw new CertPathValidatorException("unrecognized " +
"critical extension(s)", null, cpOriginal, cpSize-(i+1),
PKIXReason.UNRECOGNIZED_CRIT_EXT);
@ -200,26 +142,9 @@ class PKIXMasterCertPathValidator {
if (debug != null) {
debug.println("Cert path validation succeeded. (PKIX validation "
+ "algorithm)");
+ "algorithm)");
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;
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,9 +25,8 @@
package sun.security.provider.certpath;
import java.util.*;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertPathValidatorException;
@ -36,13 +35,14 @@ import java.security.cert.PKIXReason;
import java.security.cert.PolicyNode;
import java.security.cert.PolicyQualifierInfo;
import java.security.cert.X509Certificate;
import java.util.*;
import sun.security.util.Debug;
import sun.security.x509.CertificatePoliciesExtension;
import sun.security.x509.PolicyConstraintsExtension;
import sun.security.x509.PolicyMappingsExtension;
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.X509CertImpl;
import sun.security.x509.InhibitAnyPolicyExtension;
@ -88,7 +88,7 @@ class PolicyChecker extends PKIXCertPathChecker {
PolicyChecker(Set<String> initialPolicies, int certPathLen,
boolean expPolicyRequired, boolean polMappingInhibited,
boolean anyPolicyInhibited, boolean rejectPolicyQualifiers,
PolicyNodeImpl rootNode) throws CertPathValidatorException
PolicyNodeImpl rootNode)
{
if (initialPolicies.isEmpty()) {
// if no initialPolicies are specified by user, set
@ -104,18 +104,18 @@ class PolicyChecker extends PKIXCertPathChecker {
this.anyPolicyInhibited = anyPolicyInhibited;
this.rejectPolicyQualifiers = rejectPolicyQualifiers;
this.rootNode = rootNode;
init(false);
}
/**
* Initializes the internal state of the checker from parameters
* specified in the constructor
*
* @param forward a boolean indicating whether this checker should
* be initialized capable of building in the forward direction
* @exception CertPathValidatorException Exception thrown if user
* wants to enable forward checking and forward checking is not supported.
* @param forward a boolean indicating whether this checker should be
* initialized capable of building in the forward direction
* @throws CertPathValidatorException if user wants to enable forward
* checking and forward checking is not supported.
*/
@Override
public void init(boolean forward) throws CertPathValidatorException {
if (forward) {
throw new CertPathValidatorException
@ -136,6 +136,7 @@ class PolicyChecker extends PKIXCertPathChecker {
*
* @return true if forward checking is supported, false otherwise
*/
@Override
public boolean isForwardCheckingSupported() {
return false;
}
@ -150,13 +151,14 @@ class PolicyChecker extends PKIXCertPathChecker {
* @return the Set of extensions supported by this PKIXCertPathChecker,
* or null if no extensions are supported
*/
@Override
public Set<String> getSupportedExtensions() {
if (supportedExts == null) {
supportedExts = new HashSet<String>();
supportedExts.add(PKIXExtensions.CertificatePolicies_Id.toString());
supportedExts.add(PKIXExtensions.PolicyMappings_Id.toString());
supportedExts.add(PKIXExtensions.PolicyConstraints_Id.toString());
supportedExts.add(PKIXExtensions.InhibitAnyPolicy_Id.toString());
supportedExts = new HashSet<String>(4);
supportedExts.add(CertificatePolicies_Id.toString());
supportedExts.add(PolicyMappings_Id.toString());
supportedExts.add(PolicyConstraints_Id.toString());
supportedExts.add(InhibitAnyPolicy_Id.toString());
supportedExts = Collections.unmodifiableSet(supportedExts);
}
return supportedExts;
@ -168,9 +170,9 @@ class PolicyChecker extends PKIXCertPathChecker {
*
* @param cert the Certificate to be processed
* @param unresCritExts the unresolved critical extensions
* @exception CertPathValidatorException Exception thrown if
* the certificate does not verify.
* @throws CertPathValidatorException if the certificate does not verify
*/
@Override
public void check(Certificate cert, Collection<String> unresCritExts)
throws CertPathValidatorException
{
@ -178,10 +180,10 @@ class PolicyChecker extends PKIXCertPathChecker {
checkPolicy((X509Certificate) cert);
if (unresCritExts != null && !unresCritExts.isEmpty()) {
unresCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString());
unresCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString());
unresCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString());
unresCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString());
unresCritExts.remove(CertificatePolicies_Id.toString());
unresCritExts.remove(PolicyMappings_Id.toString());
unresCritExts.remove(PolicyConstraints_Id.toString());
unresCritExts.remove(InhibitAnyPolicy_Id.toString());
}
}
@ -290,7 +292,7 @@ class PolicyChecker extends PKIXCertPathChecker {
if (require == 0)
explicitPolicy = require;
}
} catch (Exception e) {
} catch (IOException e) {
if (debug != null) {
debug.println("PolicyChecker.mergeExplicitPolicy "
+ "unexpected exception");
@ -339,7 +341,7 @@ class PolicyChecker extends PKIXCertPathChecker {
policyMapping = inhibit;
}
}
} catch (Exception e) {
} catch (IOException e) {
if (debug != null) {
debug.println("PolicyChecker.mergePolicyMapping "
+ "unexpected exception");
@ -372,7 +374,7 @@ class PolicyChecker extends PKIXCertPathChecker {
try {
InhibitAnyPolicyExtension inhAnyPolExt = (InhibitAnyPolicyExtension)
currCert.getExtension(PKIXExtensions.InhibitAnyPolicy_Id);
currCert.getExtension(InhibitAnyPolicy_Id);
if (inhAnyPolExt == null)
return inhibitAnyPolicy;
@ -387,7 +389,7 @@ class PolicyChecker extends PKIXCertPathChecker {
inhibitAnyPolicy = skipCerts;
}
}
} catch (Exception e) {
} catch (IOException e) {
if (debug != null) {
debug.println("PolicyChecker.mergeInhibitAnyPolicy "
+ "unexpected exception");
@ -429,7 +431,7 @@ class PolicyChecker extends PKIXCertPathChecker {
boolean policiesCritical = false;
List<PolicyInformation> policyInfo;
PolicyNodeImpl rootNode = null;
Set<PolicyQualifierInfo> anyQuals = new HashSet<PolicyQualifierInfo>();
Set<PolicyQualifierInfo> anyQuals = new HashSet<>();
if (origRootNode == null)
rootNode = null;
@ -600,7 +602,7 @@ class PolicyChecker extends PKIXCertPathChecker {
PolicyNodeImpl parentNode = (PolicyNodeImpl)anyNode.getParent();
parentNode.deleteChild(anyNode);
// 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)) {
initial.remove(node.getValidPolicy());
}
@ -697,7 +699,7 @@ class PolicyChecker extends PKIXCertPathChecker {
}
}
Set<String> expPols = new HashSet<String>();
Set<String> expPols = new HashSet<>();
expPols.add(curParExpPol);
curNode = new PolicyNodeImpl
@ -762,8 +764,7 @@ class PolicyChecker extends PKIXCertPathChecker {
}
boolean childDeleted = false;
for (int j = 0; j < maps.size(); j++) {
CertificatePolicyMap polMap = maps.get(j);
for (CertificatePolicyMap polMap : maps) {
String issuerDomain
= polMap.getIssuerIdentifier().getIdentifier().toString();
String subjectDomain
@ -816,7 +817,7 @@ class PolicyChecker extends PKIXCertPathChecker {
PolicyNodeImpl curAnyNodeParent =
(PolicyNodeImpl) curAnyNode.getParent();
Set<String> expPols = new HashSet<String>();
Set<String> expPols = new HashSet<>();
expPols.add(subjectDomain);
PolicyNodeImpl curNode = new PolicyNodeImpl

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -134,30 +134,37 @@ final class PolicyNodeImpl implements PolicyNode {
node.mCriticalityIndicator, node.mExpectedPolicySet, false);
}
@Override
public PolicyNode getParent() {
return mParent;
}
@Override
public Iterator<PolicyNodeImpl> getChildren() {
return Collections.unmodifiableSet(mChildren).iterator();
}
@Override
public int getDepth() {
return mDepth;
}
@Override
public String getValidPolicy() {
return mValidPolicy;
}
@Override
public Set<PolicyQualifierInfo> getPolicyQualifiers() {
return Collections.unmodifiableSet(mQualifierSet);
}
@Override
public Set<String> getExpectedPolicies() {
return Collections.unmodifiableSet(mExpectedPolicySet);
}
@Override
public boolean isCritical() {
return mCriticalityIndicator;
}
@ -169,12 +176,12 @@ final class PolicyNodeImpl implements PolicyNode {
*
* @return a String describing the contents of the Policy Node
*/
@Override
public String toString() {
StringBuffer buffer = new StringBuffer(this.asString());
StringBuilder buffer = new StringBuilder(this.asString());
Iterator<PolicyNodeImpl> it = getChildren();
while (it.hasNext()) {
buffer.append(it.next());
for (PolicyNodeImpl node : mChildren) {
buffer.append(node);
}
return buffer.toString();
}
@ -293,7 +300,7 @@ final class PolicyNodeImpl implements PolicyNode {
* @return a <code>Set</code> of all nodes at the specified depth
*/
Set<PolicyNodeImpl> getPolicyNodes(int depth) {
Set<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
Set<PolicyNodeImpl> set = new HashSet<>();
getPolicyNodes(depth, set);
return set;
}
@ -337,7 +344,7 @@ final class PolicyNodeImpl implements PolicyNode {
private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth,
String expectedOID, boolean matchAny) {
HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
HashSet<PolicyNodeImpl> set = new HashSet<>();
if (mDepth < depth) {
for (PolicyNodeImpl node : mChildren) {
@ -367,7 +374,7 @@ final class PolicyNodeImpl implements PolicyNode {
* @return a Set of matched <code>PolicyNode</code>s
*/
Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) {
HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
HashSet<PolicyNodeImpl> set = new HashSet<>();
if (mDepth < depth) {
for (PolicyNodeImpl node : mChildren) {
@ -396,7 +403,7 @@ final class PolicyNodeImpl implements PolicyNode {
if (mParent == null) {
return "anyPolicy ROOT\n";
} else {
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
for (int i = 0, n = getDepth(); i < n; i++) {
sb.append(" ");
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -51,9 +51,10 @@ import java.util.Set;
import javax.security.auth.x500.X500Principal;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
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.X509CertImpl;
import sun.security.x509.PolicyMappingsExtension;
@ -72,28 +73,24 @@ class ReverseBuilder extends Builder {
private Debug debug = Debug.getInstance("certpath");
Set<String> initPolicies;
private final Set<String> initPolicies;
/**
* Initialize the builder with the input parameters.
*
* @param params the parameter set used to build a certification path
*/
ReverseBuilder(PKIXBuilderParameters buildParams,
X500Principal targetSubjectDN) {
ReverseBuilder(BuilderParams buildParams) {
super(buildParams);
super(buildParams, targetSubjectDN);
Set<String> initialPolicies = buildParams.getInitialPolicies();
Set<String> initialPolicies = buildParams.initialPolicies();
initPolicies = new HashSet<String>();
if (initialPolicies.isEmpty()) {
// if no initialPolicies are specified by user, set
// initPolicies to be anyPolicy by default
initPolicies.add(PolicyChecker.ANY_POLICY);
} else {
for (String policy : initialPolicies) {
initPolicies.add(policy);
}
initPolicies.addAll(initialPolicies);
}
}
@ -106,6 +103,7 @@ class ReverseBuilder extends Builder {
* Must be an instance of <code>ReverseState</code>
* @param certStores list of CertStores
*/
@Override
Collection<X509Certificate> getMatchingCerts
(State currState, List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException
@ -138,56 +136,56 @@ class ReverseBuilder extends Builder {
(ReverseState currentState, List<CertStore> certStores)
throws CertStoreException, CertificateException, IOException {
/*
* Compose a CertSelector to filter out
* certs which do not satisfy requirements.
*
* First, retrieve clone of current target cert constraints,
* and then add more selection criteria based on current validation state.
*/
X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
/*
* Compose a CertSelector to filter out
* certs which do not satisfy requirements.
*
* First, retrieve clone of current target cert constraints, and
* then add more selection criteria based on current validation state.
*/
X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
/*
* Match on issuer (subject of previous cert)
*/
sel.setIssuer(currentState.subjectDN);
/*
* Match on issuer (subject of previous cert)
*/
sel.setIssuer(currentState.subjectDN);
/*
* Match on certificate validity date.
*/
sel.setCertificateValid(date);
/*
* Match on certificate validity date.
*/
sel.setCertificateValid(buildParams.date());
/*
* Policy processing optimizations
*/
if (currentState.explicitPolicy == 0)
sel.setPolicy(getMatchingPolicies());
/*
* Policy processing optimizations
*/
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(
/*
* 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),
null, null);
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
}*/
}*/
/*
* Require EE certs
*/
sel.setBasicConstraints(-2);
/*
* Require EE certs
*/
sel.setBasicConstraints(-2);
/* Retrieve matching certs from CertStores */
HashSet<X509Certificate> eeCerts = new HashSet<X509Certificate>();
addMatchingCerts(sel, certStores, eeCerts, true);
/* Retrieve matching certs from CertStores */
HashSet<X509Certificate> eeCerts = new HashSet<>();
addMatchingCerts(sel, certStores, eeCerts, true);
if (debug != null) {
debug.println("ReverseBuilder.getMatchingEECerts got " + eeCerts.size()
+ " certs.");
}
return eeCerts;
if (debug != null) {
debug.println("ReverseBuilder.getMatchingEECerts got "
+ eeCerts.size() + " certs.");
}
return eeCerts;
}
/*
@ -198,63 +196,71 @@ class ReverseBuilder extends Builder {
(ReverseState currentState, List<CertStore> certStores)
throws CertificateException, CertStoreException, IOException {
/*
* Compose a CertSelector to filter out
* certs which do not satisfy requirements.
*/
X509CertSelector sel = new X509CertSelector();
/*
* Compose a CertSelector to filter out
* certs which do not satisfy requirements.
*/
X509CertSelector sel = new X509CertSelector();
/*
* Match on issuer (subject of previous cert)
*/
sel.setIssuer(currentState.subjectDN);
/*
* Match on issuer (subject of previous cert)
*/
sel.setIssuer(currentState.subjectDN);
/*
* Match on certificate validity date.
*/
sel.setCertificateValid(date);
/*
* Match on certificate validity date.
*/
sel.setCertificateValid(buildParams.date());
/*
* Match on target subject name (checks that current cert's
* name constraints permit it to certify target).
* (4 is the integer type for DIRECTORY name).
*/
sel.addPathToName(4, targetCertConstraints.getSubjectAsBytes());
/*
* Match on target subject name (checks that current cert's
* name constraints permit it to certify target).
* (4 is the integer type for DIRECTORY name).
*/
byte[] subject = targetCertConstraints.getSubjectAsBytes();
if (subject != null) {
sel.addPathToName(4, subject);
} else {
X509Certificate cert = targetCertConstraints.getCertificate();
if (cert != null) {
sel.addPathToName(4,
cert.getSubjectX500Principal().getEncoded());
}
}
/*
* Policy processing optimizations
*/
if (currentState.explicitPolicy == 0)
sel.setPolicy(getMatchingPolicies());
/*
* Policy processing optimizations
*/
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(
/*
* 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),
null, null);
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
}*/
sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
}*/
/*
* Require CA certs
*/
sel.setBasicConstraints(0);
/*
* Require CA certs
*/
sel.setBasicConstraints(0);
/* Retrieve matching certs from CertStores */
ArrayList<X509Certificate> reverseCerts =
new ArrayList<X509Certificate>();
addMatchingCerts(sel, certStores, reverseCerts, true);
/* Retrieve matching certs from CertStores */
ArrayList<X509Certificate> reverseCerts = new ArrayList<>();
addMatchingCerts(sel, certStores, reverseCerts, true);
/* Sort remaining certs using name constraints */
Collections.sort(reverseCerts, new PKIXCertComparator());
/* Sort remaining certs using name constraints */
Collections.sort(reverseCerts, new PKIXCertComparator());
if (debug != null)
debug.println("ReverseBuilder.getMatchingCACerts got " +
reverseCerts.size() + " certs.");
return reverseCerts;
if (debug != null)
debug.println("ReverseBuilder.getMatchingCACerts got " +
reverseCerts.size() + " certs.");
return reverseCerts;
}
/*
@ -269,23 +275,25 @@ class ReverseBuilder extends Builder {
private Debug debug = Debug.getInstance("certpath");
@Override
public int compare(X509Certificate cert1, X509Certificate cert2) {
/*
* if either cert certifies the target, always
* put at head of list.
*/
if (cert1.getSubjectX500Principal().equals(targetSubjectDN)) {
X500Principal targetSubject = buildParams.targetSubject();
if (cert1.getSubjectX500Principal().equals(targetSubject)) {
return -1;
}
if (cert2.getSubjectX500Principal().equals(targetSubjectDN)) {
if (cert2.getSubjectX500Principal().equals(targetSubject)) {
return 1;
}
int targetDist1;
int targetDist2;
try {
X500Name targetSubjectName = X500Name.asX500Name(targetSubjectDN);
X500Name targetSubjectName = X500Name.asX500Name(targetSubject);
targetDist1 = Builder.targetDistance(
null, cert1, targetSubjectName);
targetDist2 = Builder.targetDistance(
@ -330,6 +338,7 @@ class ReverseBuilder extends Builder {
* @param currentState the current state against which the cert is verified
* @param certPathList the certPathList generated thus far
*/
@Override
void verifyCert(X509Certificate cert, State currState,
List<X509Certificate> certPathList)
throws GeneralSecurityException
@ -358,8 +367,7 @@ class ReverseBuilder extends Builder {
* of the same certificate, we reverse the certpathlist first
*/
if ((certPathList != null) && (!certPathList.isEmpty())) {
List<X509Certificate> reverseCertList =
new ArrayList<X509Certificate>();
List<X509Certificate> reverseCertList = new ArrayList<>();
for (X509Certificate c : certPathList) {
reverseCertList.add(0, c);
}
@ -374,8 +382,8 @@ class ReverseBuilder extends Builder {
}
if (debug != null)
debug.println("policyMappingFound = " + policyMappingFound);
if (cert.equals(cpListCert)){
if ((buildParams.isPolicyMappingInhibited()) ||
if (cert.equals(cpListCert)) {
if ((buildParams.policyMappingInhibited()) ||
(!policyMappingFound)){
if (debug != null)
debug.println("loop detected!!");
@ -386,7 +394,7 @@ class ReverseBuilder extends Builder {
}
/* check if target cert */
boolean finalCert = cert.getSubjectX500Principal().equals(targetSubjectDN);
boolean finalCert = cert.getSubjectX500Principal().equals(buildParams.targetSubject());
/* check if CA cert */
boolean caCert = (cert.getBasicConstraints() != -1 ? true : false);
@ -427,23 +435,20 @@ class ReverseBuilder extends Builder {
/*
* Check revocation.
*/
if (buildParams.isRevocationEnabled()) {
currentState.crlChecker.check(cert,
currentState.pubKey,
currentState.crlSign);
if (buildParams.revocationEnabled() && currentState.revChecker != null) {
currentState.revChecker.check(cert, Collections.<String>emptySet());
}
/* Check name constraints if this is not a self-issued cert */
if (finalCert || !X509CertImpl.isSelfIssued(cert)){
if (currentState.nc != null){
if (currentState.nc != null) {
try {
if (!currentState.nc.verify(cert)){
throw new CertPathValidatorException
("name constraints check failed", null, null, -1,
PKIXReason.INVALID_NAME);
}
} catch (IOException ioe){
} catch (IOException ioe) {
throw new CertPathValidatorException(ioe);
}
}
@ -457,7 +462,7 @@ class ReverseBuilder extends Builder {
(currentState.certIndex, initPolicies,
currentState.explicitPolicy, currentState.policyMapping,
currentState.inhibitAnyPolicy,
buildParams.getPolicyQualifiersRejected(), currentState.rootNode,
buildParams.policyQualifiersRejected(), currentState.rootNode,
certImpl, finalCert);
/*
@ -482,15 +487,15 @@ class ReverseBuilder extends Builder {
* already checked. If there are any left, throw an exception!
*/
if (!unresolvedCritExts.isEmpty()) {
unresolvedCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.NameConstraints_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.SubjectAlternativeName_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
unresolvedCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString());
unresolvedCritExts.remove(BasicConstraints_Id.toString());
unresolvedCritExts.remove(NameConstraints_Id.toString());
unresolvedCritExts.remove(CertificatePolicies_Id.toString());
unresolvedCritExts.remove(PolicyMappings_Id.toString());
unresolvedCritExts.remove(PolicyConstraints_Id.toString());
unresolvedCritExts.remove(InhibitAnyPolicy_Id.toString());
unresolvedCritExts.remove(SubjectAlternativeName_Id.toString());
unresolvedCritExts.remove(KeyUsage_Id.toString());
unresolvedCritExts.remove(ExtendedKeyUsage_Id.toString());
if (!unresolvedCritExts.isEmpty())
throw new CertPathValidatorException
@ -501,8 +506,8 @@ class ReverseBuilder extends Builder {
/*
* Check signature.
*/
if (buildParams.getSigProvider() != null) {
cert.verify(currentState.pubKey, buildParams.getSigProvider());
if (buildParams.sigProvider() != null) {
cert.verify(currentState.pubKey, buildParams.sigProvider());
} else {
cert.verify(currentState.pubKey);
}
@ -515,8 +520,9 @@ class ReverseBuilder extends Builder {
* @param cert the certificate to test
* @return a boolean value indicating whether the cert completes the path.
*/
@Override
boolean isPathCompleted(X509Certificate cert) {
return cert.getSubjectX500Principal().equals(targetSubjectDN);
return cert.getSubjectX500Principal().equals(buildParams.targetSubject());
}
/** Adds the certificate to the certPathList
@ -524,6 +530,7 @@ class ReverseBuilder extends Builder {
* @param cert the certificate to be added
* @param certPathList the certification path list
*/
@Override
void addCertToPath(X509Certificate cert,
LinkedList<X509Certificate> certPathList) {
certPathList.addLast(cert);
@ -533,6 +540,7 @@ class ReverseBuilder extends Builder {
*
* @param certPathList the certification path list
*/
@Override
void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
certPathList.removeLast();
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -40,6 +40,7 @@ import java.util.ListIterator;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
import sun.security.provider.certpath.PKIX.BuilderParams;
import sun.security.util.Debug;
import sun.security.x509.NameConstraintsExtension;
import sun.security.x509.SubjectKeyIdentifierExtension;
@ -94,7 +95,7 @@ class ReverseState implements State {
private boolean init = true;
/* the checker used for revocation status */
public CrlRevocationChecker crlChecker;
RevocationChecker revChecker;
/* the algorithm checker */
AlgorithmChecker algorithmChecker;
@ -105,7 +106,7 @@ class ReverseState implements State {
/* Flag indicating if current cert can vouch for the CRL for
* the next cert
*/
public boolean crlSign = true;
boolean crlSign = true;
/**
* Returns a boolean flag indicating if the state is initial
@ -113,6 +114,7 @@ class ReverseState implements State {
*
* @return boolean flag indicating if the state is initial (just starting)
*/
@Override
public boolean isInitial() {
return init;
}
@ -120,44 +122,32 @@ class ReverseState implements State {
/**
* Display state for debugging purposes
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
try {
sb.append("State [");
sb.append("\n subjectDN of last cert: " + subjectDN);
sb.append("\n subjectKeyIdentifier: " + String.valueOf(subjKeyId));
sb.append("\n nameConstraints: " + String.valueOf(nc));
sb.append("\n certIndex: " + certIndex);
sb.append("\n explicitPolicy: " + explicitPolicy);
sb.append("\n policyMapping: " + policyMapping);
sb.append("\n inhibitAnyPolicy: " + inhibitAnyPolicy);
sb.append("\n rootNode: " + rootNode);
sb.append("\n remainingCACerts: " + remainingCACerts);
sb.append("\n crlSign: " + crlSign);
sb.append("\n init: " + init);
sb.append("\n]\n");
} catch (Exception e) {
if (debug != null) {
debug.println("ReverseState.toString() unexpected exception");
e.printStackTrace();
}
}
StringBuilder sb = new StringBuilder();
sb.append("State [");
sb.append("\n subjectDN of last cert: ").append(subjectDN);
sb.append("\n subjectKeyIdentifier: ").append
(String.valueOf(subjKeyId));
sb.append("\n nameConstraints: ").append(String.valueOf(nc));
sb.append("\n certIndex: ").append(certIndex);
sb.append("\n explicitPolicy: ").append(explicitPolicy);
sb.append("\n policyMapping: ").append(policyMapping);
sb.append("\n inhibitAnyPolicy: ").append(inhibitAnyPolicy);
sb.append("\n rootNode: ").append(rootNode);
sb.append("\n remainingCACerts: ").append(remainingCACerts);
sb.append("\n crlSign: ").append(crlSign);
sb.append("\n init: ").append(init);
sb.append("\n]\n");
return sb.toString();
}
/**
* Initialize the state.
*
* @param maxPathLen The maximum number of CA certs in a path, where -1
* 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
* @param buildParams builder parameters
*/
public void initState(int maxPathLen, boolean explicitPolicyRequired,
boolean policyMappingInhibited, boolean anyPolicyInhibited,
List<PKIXCertPathChecker> certPathCheckers)
public void initState(BuilderParams buildParams)
throws CertPathValidatorException
{
/*
@ -165,60 +155,52 @@ class ReverseState implements State {
* Note that -1 maxPathLen implies unlimited.
* 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 */
if (explicitPolicyRequired) {
if (buildParams.explicitPolicyRequired()) {
explicitPolicy = 0;
} else {
// unconstrained if maxPathLen is -1,
// otherwise, we want to initialize this to the value of the
// longest possible path + 1 (i.e. maxpathlen + finalcert + 1)
explicitPolicy = (maxPathLen == -1)
? maxPathLen
: maxPathLen + 2;
explicitPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
}
/* Initialize policy mapping state variable */
if (policyMappingInhibited) {
if (buildParams.policyMappingInhibited()) {
policyMapping = 0;
} else {
policyMapping = (maxPathLen == -1)
? maxPathLen
: maxPathLen + 2;
policyMapping = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
}
/* Initialize inhibit any policy state variable */
if (anyPolicyInhibited) {
if (buildParams.anyPolicyInhibited()) {
inhibitAnyPolicy = 0;
} else {
inhibitAnyPolicy = (maxPathLen == -1)
? maxPathLen
: maxPathLen + 2;
inhibitAnyPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
}
/* Initialize certIndex */
certIndex = 1;
/* Initialize policy tree */
Set<String> initExpPolSet = new HashSet<String>(1);
Set<String> initExpPolSet = new HashSet<>(1);
initExpPolSet.add(PolicyChecker.ANY_POLICY);
rootNode = new PolicyNodeImpl
(null, PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null,
false, initExpPolSet, false);
/*
* Initialize each user-defined checker
* Shallow copy the checkers
*/
if (certPathCheckers != null) {
/* Shallow copy the checkers */
userCheckers = new ArrayList<PKIXCertPathChecker>(certPathCheckers);
/* initialize each checker (just in case) */
for (PKIXCertPathChecker checker : certPathCheckers) {
checker.init(false);
}
} else {
userCheckers = new ArrayList<PKIXCertPathChecker>();
userCheckers = new ArrayList<>(buildParams.certPathCheckers());
/* initialize each checker (just in case) */
for (PKIXCertPathChecker checker : userCheckers) {
checker.init(false);
}
/* Start by trusting the cert to sign CRLs */
@ -231,8 +213,9 @@ class ReverseState implements State {
* Update the state with the specified trust anchor.
*
* @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
{
trustAnchor = anchor;
@ -244,14 +227,26 @@ class ReverseState implements State {
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.
boolean revCheckerAdded = false;
for (PKIXCertPathChecker checker : userCheckers) {
if (checker instanceof AlgorithmChecker) {
((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;
}
@ -310,7 +305,7 @@ class ReverseState implements State {
subjKeyId = icert.getSubjectKeyIdentifierExtension();
/* update crlSign */
crlSign = CrlRevocationChecker.certCanSignCrl(cert);
crlSign = RevocationChecker.certCanSignCrl(cert);
/* update current name constraints */
if (nc != null) {
@ -349,6 +344,7 @@ class ReverseState implements State {
*
* @return boolean flag indicating if key lacking parameters encountered.
*/
@Override
public boolean keyParamsNeeded() {
/* when building in reverse, we immediately get parameters needed
* or else throw an exception
@ -365,6 +361,7 @@ class ReverseState implements State {
* because some of them (e.g., subjKeyId) will
* not have their contents modified by subsequent calls to updateState.
*/
@Override
@SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
public Object clone() {
try {

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,10 +26,8 @@
package sun.security.provider.certpath;
import java.io.IOException;
import java.security.AccessController;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.Principal;
import java.security.PublicKey;
import java.security.cert.*;
import java.security.cert.PKIXReason;
@ -37,7 +35,6 @@ import java.security.interfaces.DSAPublicKey;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@ -45,9 +42,8 @@ import java.util.LinkedList;
import java.util.Set;
import javax.security.auth.x500.X500Principal;
import sun.security.action.GetBooleanSecurityPropertyAction;
import sun.security.x509.X500Name;
import sun.security.x509.PKIXExtensions;
import sun.security.provider.certpath.PKIX.BuilderParams;
import static sun.security.x509.PKIXExtensions.*;
import sun.security.util.Debug;
/**
@ -78,16 +74,12 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/*
* private objects shared by methods
*/
private PKIXBuilderParameters buildParams;
private BuilderParams buildParams;
private CertificateFactory cf;
private boolean pathCompleted = false;
private X500Principal targetSubjectDN;
private PolicyNode policyTreeResult;
private TrustAnchor trustAnchor;
private PublicKey finalPublicKey;
private X509CertSelector targetSel;
private List<CertStore> orderedCertStores;
private boolean onlyEECert = false;
/**
* Create an instance of <code>SunCertPathBuilder</code>.
@ -100,9 +92,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
} catch (CertificateException 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 {
* @throws InvalidAlgorithmParameterException if the given parameters are
* inappropriate for this certification path builder.
*/
@Override
public CertPathBuilderResult engineBuild(CertPathParameters params)
throws CertPathBuilderException, InvalidAlgorithmParameterException {
@ -132,66 +127,20 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
debug.println("SunCertPathBuilder.engineBuild(" + params + ")");
}
if (!(params instanceof PKIXBuilderParameters)) {
throw new InvalidAlgorithmParameterException("inappropriate " +
"parameter type, must be an instance of PKIXBuilderParameters");
}
buildParams = PKIX.checkBuilderParams(params);
return build();
}
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>>();
CertPathBuilderResult result =
buildCertPath(buildForward, false, adjList);
private PKIXCertPathBuilderResult build() throws CertPathBuilderException {
List<List<Vertex>> adjList = new ArrayList<>();
PKIXCertPathBuilderResult result = buildCertPath(false, adjList);
if (result == null) {
if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild: 2nd pass");
}
// try again
adjList.clear();
result = buildCertPath(buildForward, true, adjList);
result = buildCertPath(true, adjList);
if (result == null) {
throw new SunCertPathBuilderException("unable to find valid "
+ "certification path to requested target",
@ -201,24 +150,23 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
return result;
}
private CertPathBuilderResult buildCertPath(boolean buildForward,
boolean searchAllCertStores, List<List<Vertex>> adjList)
throws CertPathBuilderException {
private PKIXCertPathBuilderResult buildCertPath(boolean searchAllCertStores,
List<List<Vertex>> adjList)
throws CertPathBuilderException
{
// Init shared variables and build certification path
pathCompleted = false;
trustAnchor = null;
finalPublicKey = null;
policyTreeResult = null;
LinkedList<X509Certificate> certPathList =
new LinkedList<X509Certificate>();
LinkedList<X509Certificate> certPathList = new LinkedList<>();
try {
if (buildForward) {
if (buildParams.buildForward()) {
buildForward(adjList, certPathList, searchAllCertStores);
} else {
buildReverse(adjList, certPathList);
}
} catch (Exception e) {
} catch (GeneralSecurityException | IOException e) {
if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild() exception in "
+ "build");
@ -242,11 +190,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
Collections.reverse(certPathList);
return new SunCertPathBuilderResult(
cf.generateCertPath(certPathList), this.trustAnchor,
cf.generateCertPath(certPathList), trustAnchor,
policyTreeResult, finalPublicKey,
new AdjacencyList(adjList));
}
} catch (Exception e) {
} catch (CertificateException e) {
if (debug != null) {
debug.println("SunCertPathBuilder.engineBuild() exception "
+ "in wrap-up");
@ -264,12 +212,13 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Private build reverse method.
*/
private void buildReverse(List<List<Vertex>> adjacencyList,
LinkedList<X509Certificate> certPathList) throws Exception
LinkedList<X509Certificate> certPathList)
throws GeneralSecurityException, IOException
{
if (debug != null) {
debug.println("SunCertPathBuilder.buildReverse()...");
debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: "
+ buildParams.getInitialPolicies());
+ buildParams.initialPolicies());
}
ReverseState currentState = new ReverseState();
@ -281,11 +230,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Perform a search using each trust anchor, until a valid
* path is found
*/
Iterator<TrustAnchor> iter = buildParams.getTrustAnchors().iterator();
Iterator<TrustAnchor> iter = buildParams.trustAnchors().iterator();
while (iter.hasNext()) {
TrustAnchor anchor = iter.next();
/* check if anchor satisfies target constraints */
if (anchorIsTarget(anchor, targetSel)) {
if (anchorIsTarget(anchor, buildParams.targetCertConstraints())) {
this.trustAnchor = anchor;
this.pathCompleted = true;
this.finalPublicKey = anchor.getTrustedCert().getPublicKey();
@ -293,21 +242,15 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
}
/* Initialize current state */
currentState.initState(buildParams.getMaxPathLength(),
buildParams.isExplicitPolicyRequired(),
buildParams.isPolicyMappingInhibited(),
buildParams.isAnyPolicyInhibited(),
buildParams.getCertPathCheckers());
currentState.updateState(anchor);
// init the crl checker
currentState.crlChecker =
new CrlRevocationChecker(null, buildParams, null, onlyEECert);
currentState.initState(buildParams);
currentState.updateState(anchor, buildParams);
currentState.algorithmChecker = new AlgorithmChecker(anchor);
try {
depthFirstSearchReverse(null, currentState,
new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
certPathList);
} catch (Exception e) {
new ReverseBuilder(buildParams),
adjacencyList, certPathList);
} catch (GeneralSecurityException | IOException e) {
// continue on error if more anchors to try
if (iter.hasNext())
continue;
@ -331,7 +274,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Private build forward method.
*/
private void buildForward(List<List<Vertex>> adjacencyList,
LinkedList<X509Certificate> certPathList, boolean searchAllCertStores)
LinkedList<X509Certificate> certPathList,
boolean searchAllCertStores)
throws GeneralSecurityException, IOException
{
if (debug != null) {
@ -340,20 +284,16 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/* Initialize current state */
ForwardState currentState = new ForwardState();
currentState.initState(buildParams.getCertPathCheckers());
currentState.initState(buildParams.certPathCheckers());
/* Initialize adjacency list */
adjacencyList.clear();
adjacencyList.add(new LinkedList<Vertex>());
// init the crl checker
currentState.crlChecker
= new CrlRevocationChecker(null, buildParams, null, onlyEECert);
depthFirstSearchForward(targetSubjectDN, currentState,
new ForwardBuilder
(buildParams, targetSubjectDN, searchAllCertStores, onlyEECert),
adjacencyList, certPathList);
depthFirstSearchForward(buildParams.targetSubject(), currentState,
new ForwardBuilder(buildParams,
searchAllCertStores),
adjacencyList, certPathList);
}
/*
@ -371,27 +311,28 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* @param dN the distinguished name being currently searched for certs
* @param currentState the current PKIX validation state
*/
void depthFirstSearchForward(X500Principal dN, ForwardState currentState,
ForwardBuilder builder, List<List<Vertex>> adjList,
LinkedList<X509Certificate> certPathList)
private void depthFirstSearchForward(X500Principal dN,
ForwardState currentState,
ForwardBuilder builder,
List<List<Vertex>> adjList,
LinkedList<X509Certificate> cpList)
throws GeneralSecurityException, IOException
{
//XXX This method should probably catch & handle exceptions
if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward(" + dN
+ ", " + currentState.toString() + ")");
+ ", " + currentState.toString() + ")");
}
/*
* Find all the certificates issued to dN which
* satisfy the PKIX certification path constraints.
*/
List<Vertex> vertices = addVertices
(builder.getMatchingCerts(currentState, orderedCertStores), adjList);
Collection<X509Certificate> certs =
builder.getMatchingCerts(currentState, buildParams.certStores());
List<Vertex> vertices = addVertices(certs, adjList);
if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward(): "
+ "certs.size=" + vertices.size());
+ "certs.size=" + vertices.size());
}
/*
@ -411,14 +352,14 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* the next matching cert is tried.
*/
ForwardState nextState = (ForwardState) currentState.clone();
X509Certificate cert = (X509Certificate) vertex.getCertificate();
X509Certificate cert = vertex.getCertificate();
try {
builder.verifyCert(cert, nextState, certPathList);
builder.verifyCert(cert, nextState, cpList);
} catch (GeneralSecurityException gse) {
if (debug != null) {
debug.println("SunCertPathBuilder.depthFirstSearchForward()"
+ ": validation failed: " + gse);
+ ": validation failed: " + gse);
gse.printStackTrace();
}
vertex.setThrowable(gse);
@ -436,51 +377,44 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
*/
if (builder.isPathCompleted(cert)) {
BasicChecker basicChecker = null;
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward()"
+ ": commencing final verification");
+ ": commencing final verification");
ArrayList<X509Certificate> appendedCerts =
new ArrayList<X509Certificate>(certPathList);
List<X509Certificate> appendedCerts = new ArrayList<>(cpList);
/*
* if the trust anchor selected is specified as a trusted
* public key rather than a trusted cert, then verify this
* 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) {
appendedCerts.add(0, cert);
}
HashSet<String> initExpPolSet = new HashSet<String>(1);
initExpPolSet.add(PolicyChecker.ANY_POLICY);
Set<String> initExpPolSet =
Collections.singleton(PolicyChecker.ANY_POLICY);
PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
List<PKIXCertPathChecker> checkers = new ArrayList<>();
PolicyChecker policyChecker
= new PolicyChecker(buildParams.getInitialPolicies(),
appendedCerts.size(),
buildParams.isExplicitPolicyRequired(),
buildParams.isPolicyMappingInhibited(),
buildParams.isAnyPolicyInhibited(),
buildParams.getPolicyQualifiersRejected(),
rootNode);
= new PolicyChecker(buildParams.initialPolicies(),
appendedCerts.size(),
buildParams.explicitPolicyRequired(),
buildParams.policyMappingInhibited(),
buildParams.anyPolicyInhibited(),
buildParams.policyQualifiersRejected(),
rootNode);
List<PKIXCertPathChecker> userCheckers = new
ArrayList<PKIXCertPathChecker>
(buildParams.getCertPathCheckers());
int mustCheck = 0;
userCheckers.add(mustCheck, policyChecker);
mustCheck++;
checkers.add(policyChecker);
// add the algorithm checker
userCheckers.add(mustCheck,
new AlgorithmChecker(builder.trustAnchor));
mustCheck++;
checkers.add(new AlgorithmChecker(builder.trustAnchor));
BasicChecker basicChecker = null;
if (nextState.keyParamsNeeded()) {
PublicKey rootKey = cert.getPublicKey();
if (builder.trustAnchor.getTrustedCert() == null) {
@ -495,24 +429,38 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
(cert.getSubjectX500Principal(), rootKey, null);
// add the basic checker
basicChecker = new BasicChecker(anchor,
builder.date,
buildParams.getSigProvider(),
true);
userCheckers.add(mustCheck, basicChecker);
mustCheck++;
basicChecker = new BasicChecker(anchor, buildParams.date(),
buildParams.sigProvider(),
true);
checkers.add(basicChecker);
}
// add the crl revocation checker
if (buildParams.isRevocationEnabled()) {
userCheckers.add(mustCheck, new CrlRevocationChecker
(anchor, buildParams, null, onlyEECert));
mustCheck++;
buildParams.setCertPath(cf.generateCertPath(appendedCerts));
boolean revCheckerAdded = false;
List<PKIXCertPathChecker> ckrs = buildParams.certPathCheckers();
for (PKIXCertPathChecker ckr : ckrs) {
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?
for (int i=0; i<appendedCerts.size(); i++) {
for (int i = 0; i < appendedCerts.size(); i++) {
X509Certificate currCert = appendedCerts.get(i);
if (debug != null)
debug.println("current subject = "
@ -523,18 +471,15 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
unresCritExts = Collections.<String>emptySet();
}
for (int j=0; j<userCheckers.size(); j++) {
PKIXCertPathChecker currChecker = userCheckers.get(j);
if (j < mustCheck ||
!currChecker.isForwardCheckingSupported()) {
for (PKIXCertPathChecker currChecker : checkers) {
if (!currChecker.isForwardCheckingSupported()) {
if (i == 0) {
currChecker.init(false);
// The user specified
// AlgorithmChecker may not be
// able to set the trust anchor until now.
if (j >= mustCheck &&
currChecker instanceof AlgorithmChecker) {
if (currChecker instanceof AlgorithmChecker) {
((AlgorithmChecker)currChecker).
trySetTrustAnchor(builder.trustAnchor);
}
@ -560,7 +505,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* are capable of processing.
*/
for (PKIXCertPathChecker checker :
buildParams.getCertPathCheckers())
buildParams.certPathCheckers())
{
if (checker.isForwardCheckingSupported()) {
Set<String> suppExts =
@ -572,24 +517,16 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
}
if (!unresCritExts.isEmpty()) {
unresCritExts.remove
(PKIXExtensions.BasicConstraints_Id.toString());
unresCritExts.remove
(PKIXExtensions.NameConstraints_Id.toString());
unresCritExts.remove
(PKIXExtensions.CertificatePolicies_Id.toString());
unresCritExts.remove
(PKIXExtensions.PolicyMappings_Id.toString());
unresCritExts.remove
(PKIXExtensions.PolicyConstraints_Id.toString());
unresCritExts.remove
(PKIXExtensions.InhibitAnyPolicy_Id.toString());
unresCritExts.remove(PKIXExtensions.
unresCritExts.remove(BasicConstraints_Id.toString());
unresCritExts.remove(NameConstraints_Id.toString());
unresCritExts.remove(CertificatePolicies_Id.toString());
unresCritExts.remove(PolicyMappings_Id.toString());
unresCritExts.remove(PolicyConstraints_Id.toString());
unresCritExts.remove(InhibitAnyPolicy_Id.toString());
unresCritExts.remove(
SubjectAlternativeName_Id.toString());
unresCritExts.remove
(PKIXExtensions.KeyUsage_Id.toString());
unresCritExts.remove
(PKIXExtensions.ExtendedKeyUsage_Id.toString());
unresCritExts.remove(KeyUsage_Id.toString());
unresCritExts.remove(ExtendedKeyUsage_Id.toString());
if (!unresCritExts.isEmpty()) {
throw new CertPathValidatorException
@ -606,10 +543,10 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/*
* if the user specified a trusted public key rather than
* 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)
builder.addCertToPath(cert, certPathList);
builder.addCertToPath(cert, cpList);
// Save the trust anchor
this.trustAnchor = builder.trustAnchor;
@ -620,10 +557,10 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
finalPublicKey = basicChecker.getPublicKey();
} else {
Certificate finalCert;
if (certPathList.size() == 0) {
if (cpList.isEmpty()) {
finalCert = builder.trustAnchor.getTrustedCert();
} else {
finalCert = certPathList.get(certPathList.size()-1);
finalCert = cpList.getLast();
}
finalPublicKey = finalCert.getPublicKey();
}
@ -631,7 +568,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
policyTreeResult = policyChecker.getPolicyTree();
return;
} else {
builder.addCertToPath(cert, certPathList);
builder.addCertToPath(cert, cpList);
}
/* Update the PKIX state */
@ -645,8 +582,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
vertex.setIndex(adjList.size() - 1);
/* recursively search for matching certs at next dN */
depthFirstSearchForward(cert.getIssuerX500Principal(), nextState, builder,
adjList, certPathList);
depthFirstSearchForward(cert.getIssuerX500Principal(), nextState,
builder, adjList, cpList);
/*
* If path has been completed, return ASAP!
@ -662,8 +599,8 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
*/
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchForward()"
+ ": backtracking");
builder.removeFinalCertFromPath(certPathList);
+ ": backtracking");
builder.removeFinalCertFromPath(cpList);
}
}
}
@ -683,9 +620,11 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* @param dN the distinguished name being currently searched for certs
* @param currentState the current PKIX validation state
*/
void depthFirstSearchReverse(X500Principal dN, ReverseState currentState,
ReverseBuilder builder, List<List<Vertex>> adjList,
LinkedList<X509Certificate> certPathList)
private void depthFirstSearchReverse(X500Principal dN,
ReverseState currentState,
ReverseBuilder builder,
List<List<Vertex>> adjList,
LinkedList<X509Certificate> cpList)
throws GeneralSecurityException, IOException
{
if (debug != null)
@ -696,8 +635,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Find all the certificates issued by dN which
* satisfy the PKIX certification path constraints.
*/
List<Vertex> vertices = addVertices
(builder.getMatchingCerts(currentState, orderedCertStores), adjList);
Collection<X509Certificate> certs =
builder.getMatchingCerts(currentState, buildParams.certStores());
List<Vertex> vertices = addVertices(certs, adjList);
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchReverse(): "
+ "certs.size=" + vertices.size());
@ -717,9 +657,9 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* the next matching cert is tried.
*/
ReverseState nextState = (ReverseState) currentState.clone();
X509Certificate cert = (X509Certificate) vertex.getCertificate();
X509Certificate cert = vertex.getCertificate();
try {
builder.verifyCert(cert, nextState, certPathList);
builder.verifyCert(cert, nextState, cpList);
} catch (GeneralSecurityException gse) {
if (debug != null)
debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
@ -733,7 +673,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* self-signed cert) and update state
*/
if (!currentState.isInitial())
builder.addCertToPath(cert, certPathList);
builder.addCertToPath(cert, cpList);
// save trust anchor
this.trustAnchor = currentState.trustAnchor;
@ -782,7 +722,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
/* recursively search for matching certs at next dN */
depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState,
builder, adjList, certPathList);
builder, adjList, cpList);
/*
* If path has been completed, return ASAP!
@ -800,7 +740,7 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
+ ": backtracking");
if (!currentState.isInitial())
builder.removeFinalCertFromPath(certPathList);
builder.removeFinalCertFromPath(cpList);
}
}
if (debug != null)
@ -812,13 +752,14 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Adds a collection of matching certificates to the
* adjacency list.
*/
private List<Vertex> addVertices(Collection<X509Certificate> certs,
List<List<Vertex>> adjList) {
private static List<Vertex> addVertices(Collection<X509Certificate> certs,
List<List<Vertex>> adjList)
{
List<Vertex> l = adjList.get(adjList.size() - 1);
for (X509Certificate cert : certs) {
Vertex v = new Vertex(cert);
l.add(v);
Vertex v = new Vertex(cert);
l.add(v);
}
return l;
@ -828,53 +769,13 @@ public final class SunCertPathBuilder extends CertPathBuilderSpi {
* Returns true if trust anchor certificate matches specified
* certificate constraints.
*/
private boolean anchorIsTarget(TrustAnchor anchor, X509CertSelector sel) {
private static boolean anchorIsTarget(TrustAnchor anchor,
CertSelector sel)
{
X509Certificate anchorCert = anchor.getTrustedCert();
if (anchorCert != null) {
return sel.match(anchorCert);
}
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;
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,12 +25,11 @@
package sun.security.provider.certpath;
import java.util.Set;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.cert.*;
import java.util.Set;
/**
* This class specifies the set of parameters used as input for the Sun
@ -120,8 +119,9 @@ public class SunCertPathBuilderParameters extends PKIXBuilderParameters {
*
* @return a formatted string describing the parameters.
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
sb.append("[\n");
sb.append(super.toString());
sb.append(" Build Forward Flag: " + String.valueOf(buildForward) + "\n");

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -213,6 +213,7 @@ class URICertStore extends CertStoreSpi {
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
@Override
@SuppressWarnings("unchecked")
public synchronized Collection<X509Certificate> engineGetCertificates
(CertSelector selector) throws CertStoreException {
@ -322,6 +323,7 @@ class URICertStore extends CertStoreSpi {
* match the specified selector
* @throws CertStoreException if an exception occurs
*/
@Override
@SuppressWarnings("unchecked")
public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)
throws CertStoreException {
@ -418,14 +420,14 @@ class URICertStore extends CertStoreSpi {
URICertStoreParameters(URI uri) {
this.uri = uri;
}
public boolean equals(Object obj) {
@Override public boolean equals(Object obj) {
if (!(obj instanceof URICertStoreParameters)) {
return false;
}
URICertStoreParameters params = (URICertStoreParameters) obj;
return uri.equals(params.uri);
}
public int hashCode() {
@Override public int hashCode() {
if (hashCode == 0) {
int result = 17;
result = 37*result + uri.hashCode();
@ -433,7 +435,7 @@ class URICertStore extends CertStoreSpi {
}
return hashCode;
}
public Object clone() {
@Override public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,12 +25,11 @@
package sun.security.provider.certpath;
import sun.security.util.Debug;
import java.security.cert.Certificate;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import sun.security.util.Debug;
import sun.security.x509.AuthorityKeyIdentifierExtension;
import sun.security.x509.KeyIdentifier;
import sun.security.x509.SubjectKeyIdentifierExtension;
@ -50,17 +49,17 @@ import sun.security.x509.X509CertImpl;
public class Vertex {
private static final Debug debug = Debug.getInstance("certpath");
private Certificate cert;
private int index;
private Throwable throwable;
private X509Certificate cert;
private int index;
private Throwable throwable;
/**
* Constructor; creates vertex with index of -1
* 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.index = -1;
}
@ -68,9 +67,9 @@ public class Vertex {
/**
* return the certificate for this vertex
*
* @returns Certificate
* @returns X509Certificate
*/
public Certificate getCertificate() {
public X509Certificate getCertificate() {
return cert;
}
@ -121,6 +120,7 @@ public class Vertex {
*
* @returns String representation of vertex
*/
@Override
public String toString() {
return certToString() + throwableToString() + indexToString();
}
@ -132,70 +132,65 @@ public class Vertex {
* @returns String representation of certificate info
*/
public String certToString() {
String out = "";
if (cert == null || ! (cert instanceof X509Certificate))
return "Cert: Not an X509Certificate\n";
StringBuilder sb = new StringBuilder();
X509CertImpl x509Cert = null;
try {
x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
x509Cert = X509CertImpl.toImpl(cert);
} catch (CertificateException ce) {
if (debug != null) {
debug.println("Vertex.certToString() unexpected exception");
ce.printStackTrace();
}
return out;
return sb.toString();
}
out = "Issuer: " + x509Cert.getIssuerX500Principal() + "\n";
out = out + "Subject: " + x509Cert.getSubjectX500Principal() + "\n";
out = out + "SerialNum: " + (x509Cert.getSerialNumber()).toString(16) + "\n";
out = out + "Expires: " + x509Cert.getNotAfter().toString() + "\n";
sb.append("Issuer: ").append
(x509Cert.getIssuerX500Principal()).append("\n");
sb.append("Subject: ").append
(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();
if (iUID != null) {
out = out + "IssuerUID: ";
for (int i=0; i < iUID.length; i++) {
out = out + (iUID[i]?1:0);
sb.append("IssuerUID: ");
for (boolean b : iUID) {
sb.append(b ? 1 : 0);
}
out = out + "\n";
sb.append("\n");
}
boolean[] sUID = x509Cert.getSubjectUniqueID();
if (sUID != null) {
out = out + "SubjectUID: ";
for (int i=0; i< sUID.length; i++) {
out = out + (sUID[i]?1:0);
sb.append("SubjectUID: ");
for (boolean b : sUID) {
sb.append(b ? 1 : 0);
}
out = out + "\n";
sb.append("\n");
}
SubjectKeyIdentifierExtension sKeyID = null;
try {
sKeyID = x509Cert.getSubjectKeyIdentifierExtension();
SubjectKeyIdentifierExtension sKeyID =
x509Cert.getSubjectKeyIdentifierExtension();
if (sKeyID != null) {
KeyIdentifier keyID = sKeyID.get(
SubjectKeyIdentifierExtension.KEY_ID);
out = out + "SubjKeyID: " + keyID.toString();
sb.append("SubjKeyID: ").append(keyID.toString());
}
} catch (Exception e) {
AuthorityKeyIdentifierExtension aKeyID =
x509Cert.getAuthorityKeyIdentifierExtension();
if (aKeyID != null) {
KeyIdentifier keyID = (KeyIdentifier)aKeyID.get(
AuthorityKeyIdentifierExtension.KEY_ID);
sb.append("AuthKeyID: ").append(keyID.toString());
}
} catch (IOException e) {
if (debug != null) {
debug.println("Vertex.certToString() unexpected exception");
e.printStackTrace();
}
}
AuthorityKeyIdentifierExtension aKeyID = null;
try {
aKeyID = x509Cert.getAuthorityKeyIdentifierExtension();
if (aKeyID != null) {
KeyIdentifier keyID = (KeyIdentifier)aKeyID.get(
AuthorityKeyIdentifierExtension.KEY_ID);
out = out + "AuthKeyID: " + keyID.toString();
}
} catch (Exception e) {
if (debug != null) {
debug.println("Vertex.certToString() 2 unexpected exception");
e.printStackTrace();
}
}
return out;
return sb.toString();
}
/**
@ -205,13 +200,13 @@ public class Vertex {
* @returns String form of exception (or "none")
*/
public String throwableToString() {
String out = "Exception: ";
StringBuilder sb = new StringBuilder("Exception: ");
if (throwable != null)
out = out + throwable.toString();
sb.append(throwable.toString());
else
out = out + "null";
out = out + "\n";
return out;
sb.append("null");
sb.append("\n");
return sb.toString();
}
/**
@ -222,10 +217,10 @@ public class Vertex {
* @returns String form of index as "Last cert? [Yes/No]
*/
public String moreToString() {
String out = "Last cert? ";
out = out + ((index == -1)?"Yes":"No");
out = out + "\n";
return out;
StringBuilder sb = new StringBuilder("Last cert? ");
sb.append((index == -1) ? "Yes" : "No");
sb.append("\n");
return sb.toString();
}
/**
@ -235,7 +230,6 @@ public class Vertex {
* @returns String form of index as "Index: [numeric index]"
*/
public String indexToString() {
String out = "Index: " + index + "\n";
return out;
return "Index: " + index + "\n";
}
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -33,9 +33,10 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.CertPath;
import java.security.cert.X509Certificate;
import java.util.*;
import java.security.cert.CertPath;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
@ -44,7 +45,6 @@ import sun.security.util.DerValue;
import sun.security.util.DerOutputStream;
import sun.security.util.DerInputStream;
/**
* A {@link java.security.cert.CertPath CertPath} (certification path)
* consisting exclusively of
@ -83,7 +83,7 @@ public class X509CertPath extends CertPath {
private static final Collection<String> encodingList;
static {
List<String> list = new ArrayList<String>(2);
List<String> list = new ArrayList<>(2);
list.add(PKIPATH_ENCODING);
list.add(PKCS7_ENCODING);
encodingList = Collections.unmodifiableCollection(list);
@ -272,6 +272,7 @@ public class X509CertPath extends CertPath {
* @return the encoded bytes
* @exception CertificateEncodingException if an encoding error occurs
*/
@Override
public byte[] getEncoded() throws CertificateEncodingException {
// @@@ Should cache the encoded form
return encodePKIPATH();
@ -342,6 +343,7 @@ public class X509CertPath extends CertPath {
* @exception CertificateEncodingException if an encoding error occurs or
* the encoding requested is not supported
*/
@Override
public byte[] getEncoded(String encoding)
throws CertificateEncodingException {
switch (encoding) {
@ -376,6 +378,7 @@ public class X509CertPath extends CertPath {
* @return an <code>Iterator</code> over the names of the supported
* encodings (as Strings)
*/
@Override
public Iterator<String> getEncodings() {
return getEncodingsStatic();
}
@ -387,6 +390,7 @@ public class X509CertPath extends CertPath {
* @return an immutable <code>List</code> of <code>X509Certificate</code>s
* (may be empty, but not null)
*/
@Override
public List<X509Certificate> getCertificates() {
return certs;
}

View File

@ -1,5 +1,5 @@
/*
* 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.
*
* This code is free software; you can redistribute it and/or modify it
@ -207,13 +207,14 @@ public class X509CertificatePair {
*
* @return A String describing the contents of the pair.
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
StringBuilder sb = new StringBuilder();
sb.append("X.509 Certificate Pair: [\n");
if (forward != null)
sb.append(" Forward: " + forward + "\n");
sb.append(" Forward: ").append(forward).append("\n");
if (reverse != null)
sb.append(" Reverse: " + reverse + "\n");
sb.append(" Reverse: ").append(reverse).append("\n");
sb.append("]");
return sb.toString();
}

View File

@ -31,6 +31,7 @@ import java.security.cert.CRLReason;
import java.security.cert.X509CRLEntry;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@ -500,6 +501,9 @@ public class X509CRLEntryImpl extends X509CRLEntry {
}
public Map<String, java.security.cert.Extension> getExtensions() {
if (extensions == null) {
return Collections.emptyMap();
}
Collection<Extension> exts = extensions.getAllExtensions();
HashMap<String, java.security.cert.Extension> map =
new HashMap<String, java.security.cert.Extension>(exts.size());

View File

@ -0,0 +1,179 @@
/*
* 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;
}
}
}