0N/A/*
4756N/A * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.provider.certpath;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.security.PublicKey;
0N/Aimport java.security.cert.CertificateException;
0N/Aimport java.security.cert.CertPathValidatorException;
0N/Aimport java.security.cert.PKIXCertPathChecker;
0N/Aimport java.security.cert.X509Certificate;
0N/Aimport java.security.interfaces.DSAPublicKey;
0N/Aimport java.util.ArrayList;
0N/Aimport java.util.HashSet;
0N/Aimport java.util.Iterator;
0N/Aimport java.util.List;
0N/Aimport java.util.ListIterator;
0N/Aimport javax.security.auth.x500.X500Principal;
0N/A
0N/Aimport sun.security.util.Debug;
0N/Aimport sun.security.x509.SubjectAlternativeNameExtension;
0N/Aimport sun.security.x509.GeneralNames;
0N/Aimport sun.security.x509.GeneralName;
0N/Aimport sun.security.x509.GeneralNameInterface;
0N/Aimport sun.security.x509.X500Name;
0N/Aimport sun.security.x509.X509CertImpl;
0N/A
0N/A/**
0N/A * A specification of a forward PKIX validation state
0N/A * which is initialized by each build and updated each time a
0N/A * certificate is added to the current path.
0N/A * @since 1.4
0N/A * @author Yassir Elley
0N/A */
0N/Aclass ForwardState implements State {
0N/A
0N/A private static final Debug debug = Debug.getInstance("certpath");
0N/A
0N/A /* The issuer DN of the last cert in the path */
0N/A X500Principal issuerDN;
0N/A
0N/A /* The last cert in the path */
0N/A X509CertImpl cert;
0N/A
0N/A /* The set of subjectDNs and subjectAltNames of all certs in the path */
0N/A HashSet<GeneralNameInterface> subjectNamesTraversed;
0N/A
0N/A /*
0N/A * The number of intermediate CA certs which have been traversed so
0N/A * far in the path
0N/A */
0N/A int traversedCACerts;
0N/A
0N/A /* Flag indicating if state is initial (path is just starting) */
0N/A private boolean init = true;
0N/A
0N/A /* the checker used for revocation status */
0N/A public CrlRevocationChecker crlChecker;
0N/A
4756N/A /* the untrusted certificates checker */
4756N/A UntrustedChecker untrustedChecker;
4756N/A
0N/A /* The list of user-defined checkers that support forward checking */
0N/A ArrayList<PKIXCertPathChecker> forwardCheckers;
0N/A
0N/A /* Flag indicating if key needing to inherit key parameters has been
0N/A * encountered.
0N/A */
0N/A boolean keyParamsNeededFlag = false;
0N/A
0N/A /**
0N/A * Returns a boolean flag indicating if the state is initial
0N/A * (just starting)
0N/A *
0N/A * @return boolean flag indicating if the state is initial (just starting)
0N/A */
0N/A public boolean isInitial() {
0N/A return init;
0N/A }
0N/A
0N/A /**
0N/A * Return boolean flag indicating whether a public key that needs to inherit
0N/A * key parameters has been encountered.
0N/A *
0N/A * @return boolean true if key needing to inherit parameters has been
0N/A * encountered; false otherwise.
0N/A */
0N/A public boolean keyParamsNeeded() {
0N/A return keyParamsNeededFlag;
0N/A }
0N/A
0N/A /**
0N/A * Display state for debugging purposes
0N/A */
0N/A public String toString() {
0N/A StringBuffer sb = new StringBuffer();
0N/A try {
0N/A sb.append("State [");
0N/A sb.append("\n issuerDN of last cert: " + issuerDN);
0N/A sb.append("\n traversedCACerts: " + traversedCACerts);
0N/A sb.append("\n init: " + String.valueOf(init));
0N/A sb.append("\n keyParamsNeeded: "
0N/A + String.valueOf(keyParamsNeededFlag));
0N/A sb.append("\n subjectNamesTraversed: \n" + subjectNamesTraversed);
0N/A sb.append("]\n");
0N/A } catch (Exception e) {
0N/A if (debug != null) {
0N/A debug.println("ForwardState.toString() unexpected exception");
0N/A e.printStackTrace();
0N/A }
0N/A }
0N/A return sb.toString();
0N/A }
0N/A
0N/A /**
0N/A * Initialize the state.
0N/A *
0N/A * @param certPathCheckers the list of user-defined PKIXCertPathCheckers
0N/A */
0N/A public void initState(List<PKIXCertPathChecker> certPathCheckers)
0N/A throws CertPathValidatorException
0N/A {
0N/A subjectNamesTraversed = new HashSet<GeneralNameInterface>();
0N/A traversedCACerts = 0;
0N/A
0N/A /*
0N/A * Populate forwardCheckers with every user-defined checker
0N/A * that supports forward checking and initialize the forwardCheckers
0N/A */
0N/A forwardCheckers = new ArrayList<PKIXCertPathChecker>();
0N/A if (certPathCheckers != null) {
0N/A for (PKIXCertPathChecker checker : certPathCheckers) {
0N/A if (checker.isForwardCheckingSupported()) {
0N/A checker.init(true);
0N/A forwardCheckers.add(checker);
0N/A }
0N/A }
0N/A }
0N/A
0N/A init = true;
0N/A }
0N/A
0N/A /**
0N/A * Update the state with the next certificate added to the path.
0N/A *
0N/A * @param cert the certificate which is used to update the state
0N/A */
0N/A public void updateState(X509Certificate cert)
0N/A throws CertificateException, IOException, CertPathValidatorException {
0N/A
0N/A if (cert == null)
0N/A return;
0N/A
0N/A X509CertImpl icert = X509CertImpl.toImpl(cert);
0N/A
0N/A /* see if certificate key has null parameters */
0N/A PublicKey newKey = icert.getPublicKey();
0N/A if (newKey instanceof DSAPublicKey &&
0N/A ((DSAPublicKey)newKey).getParams() == null) {
0N/A keyParamsNeededFlag = true;
0N/A }
0N/A
0N/A /* update certificate */
0N/A this.cert = icert;
0N/A
0N/A /* update issuer DN */
0N/A issuerDN = cert.getIssuerX500Principal();
0N/A
0N/A if (!X509CertImpl.isSelfIssued(cert)) {
0N/A
0N/A /*
0N/A * update traversedCACerts only if this is a non-self-issued
0N/A * intermediate CA cert
0N/A */
0N/A if (!init && cert.getBasicConstraints() != -1) {
0N/A traversedCACerts++;
0N/A }
0N/A }
0N/A
0N/A /* update subjectNamesTraversed only if this is the EE cert or if
0N/A this cert is not self-issued */
0N/A if (init || !X509CertImpl.isSelfIssued(cert)){
0N/A X500Principal subjName = cert.getSubjectX500Principal();
0N/A subjectNamesTraversed.add(X500Name.asX500Name(subjName));
0N/A
0N/A try {
0N/A SubjectAlternativeNameExtension subjAltNameExt
0N/A = icert.getSubjectAlternativeNameExtension();
0N/A if (subjAltNameExt != null) {
0N/A GeneralNames gNames = (GeneralNames)
0N/A subjAltNameExt.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
0N/A for (Iterator<GeneralName> t = gNames.iterator();
0N/A t.hasNext(); ) {
0N/A GeneralNameInterface gName = t.next().getName();
0N/A subjectNamesTraversed.add(gName);
0N/A }
0N/A }
0N/A } catch (Exception e) {
0N/A if (debug != null) {
0N/A debug.println("ForwardState.updateState() unexpected "
0N/A + "exception");
0N/A e.printStackTrace();
0N/A }
0N/A throw new CertPathValidatorException(e);
0N/A }
0N/A }
0N/A
0N/A init = false;
0N/A }
0N/A
0N/A /*
0N/A * Clone current state. The state is cloned as each cert is
0N/A * added to the path. This is necessary if backtracking occurs,
0N/A * and a prior state needs to be restored.
0N/A *
0N/A * Note that this is a SMART clone. Not all fields are fully copied,
0N/A * because some of them will
0N/A * not have their contents modified by subsequent calls to updateState.
0N/A */
0N/A public Object clone() {
0N/A try {
0N/A ForwardState clonedState = (ForwardState) super.clone();
0N/A
0N/A /* clone checkers, if cloneable */
0N/A clonedState.forwardCheckers = (ArrayList<PKIXCertPathChecker>)
0N/A forwardCheckers.clone();
0N/A ListIterator<PKIXCertPathChecker> li =
0N/A clonedState.forwardCheckers.listIterator();
0N/A while (li.hasNext()) {
0N/A PKIXCertPathChecker checker = li.next();
0N/A if (checker instanceof Cloneable) {
0N/A li.set((PKIXCertPathChecker)checker.clone());
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Shallow copy traversed names. There is no need to
0N/A * deep copy contents, since the elements of the Set
0N/A * are never modified by subsequent calls to updateState().
0N/A */
0N/A clonedState.subjectNamesTraversed
0N/A = (HashSet<GeneralNameInterface>)subjectNamesTraversed.clone();
0N/A return clonedState;
0N/A } catch (CloneNotSupportedException e) {
0N/A throw new InternalError(e.toString());
0N/A }
0N/A }
0N/A}