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:
parent
830a24d326
commit
14c586557e
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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: " +
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 "
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
289
jdk/src/share/classes/sun/security/provider/certpath/PKIX.java
Normal file
289
jdk/src/share/classes/sun/security/provider/certpath/PKIX.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(" ");
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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) {
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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());
|
||||
|
179
jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java
Normal file
179
jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user