173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/*
273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root *
573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This code is free software; you can redistribute it and/or modify it
673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * under the terms of the GNU General Public License version 2 only, as
773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * published by the Free Software Foundation.  Oracle designates this
873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * particular file as subject to the "Classpath" exception as provided
973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * by Oracle in the LICENSE file that accompanied this code.
1073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root *
1173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * This code is distributed in the hope that it will be useful, but WITHOUT
1273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * version 2 for more details (a copy is included in the LICENSE file that
1573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * accompanied this code).
1673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root *
1773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * You should have received a copy of the GNU General Public License version
1873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * 2 along with this work; if not, write to the Free Software Foundation,
1973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root *
2173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * or visit www.oracle.com if you need additional information or have any
2373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * questions.
2473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */
2573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
2673405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootpackage sun.security.provider.certpath;
2773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
2873405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.io.IOException;
2973405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.CertificateException;
3073405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.CertPathValidatorException;
3173405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.PKIXCertPathChecker;
3273405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.security.cert.X509Certificate;
3373405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.ArrayList;
3473405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.HashSet;
3573405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.List;
3673405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport java.util.ListIterator;
3773405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport javax.security.auth.x500.X500Principal;
3873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
3973405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.util.Debug;
4073405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.x509.SubjectAlternativeNameExtension;
4173405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.x509.GeneralNames;
4273405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.x509.GeneralName;
4373405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.x509.GeneralNameInterface;
4473405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.x509.X500Name;
4573405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootimport sun.security.x509.X509CertImpl;
4673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
4773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root/**
4873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * A specification of a forward PKIX validation state
4973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * which is initialized by each build and updated each time a
5073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * certificate is added to the current path.
5173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @since       1.4
5273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root * @author      Yassir Elley
5373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root */
5473405ff8729cca39da90b2e2f604062e323f6f7aKenny Rootclass ForwardState implements State {
5573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
5673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    private static final Debug debug = Debug.getInstance("certpath");
5773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
5873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /* The issuer DN of the last cert in the path */
5973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    X500Principal issuerDN;
6073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
6173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /* The last cert in the path */
6273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    X509CertImpl cert;
6373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
6473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /* The set of subjectDNs and subjectAltNames of all certs in the path */
6573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    HashSet<GeneralNameInterface> subjectNamesTraversed;
6673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
6773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /*
6873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * The number of intermediate CA certs which have been traversed so
6973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * far in the path
7073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
7173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    int traversedCACerts;
7273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
7373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /* Flag indicating if state is initial (path is just starting) */
7473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    private boolean init = true;
7573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
7673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
7773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /* the untrusted certificates checker */
784087011821a84f2a4e2b827f304bb00481d3d139Tobias Thierer    // Android-removed: Android doesn't use this mechanism for checking untrusted certificates.
794087011821a84f2a4e2b827f304bb00481d3d139Tobias Thierer    // UntrustedChecker untrustedChecker;
8073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
8173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /* The list of user-defined checkers that support forward checking */
8273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    ArrayList<PKIXCertPathChecker> forwardCheckers;
8373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
8473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /* Flag indicating if key needing to inherit key parameters has been
8573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * encountered.
8673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
8773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    boolean keyParamsNeededFlag = false;
8873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
8973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /**
9073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * Returns a boolean flag indicating if the state is initial
9173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * (just starting)
9273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     *
9373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * @return boolean flag indicating if the state is initial (just starting)
9473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
9573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    @Override
9673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    public boolean isInitial() {
9773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        return init;
9873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    }
9973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
10073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /**
10173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * Return boolean flag indicating whether a public key that needs to inherit
10273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * key parameters has been encountered.
10373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     *
10473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * @return boolean true if key needing to inherit parameters has been
10573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * encountered; false otherwise.
10673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
10773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    @Override
10873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    public boolean keyParamsNeeded() {
10973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        return keyParamsNeededFlag;
11073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    }
11173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
11273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /**
11373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * Display state for debugging purposes
11473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
11573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    @Override
11673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    public String toString() {
11773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        StringBuilder sb = new StringBuilder();
11873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        sb.append("State [");
11973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        sb.append("\n  issuerDN of last cert: ").append(issuerDN);
12073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        sb.append("\n  traversedCACerts: ").append(traversedCACerts);
12173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        sb.append("\n  init: ").append(String.valueOf(init));
12273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        sb.append("\n  keyParamsNeeded: ").append
12373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                 (String.valueOf(keyParamsNeededFlag));
12473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        sb.append("\n  subjectNamesTraversed: \n").append
12573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                 (subjectNamesTraversed);
12673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        sb.append("]\n");
12773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        return sb.toString();
12873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    }
12973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
13073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /**
13173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * Initialize the state.
13273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     *
13373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * @param certPathCheckers the list of user-defined PKIXCertPathCheckers
13473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
13573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    public void initState(List<PKIXCertPathChecker> certPathCheckers)
13673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        throws CertPathValidatorException
13773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    {
13873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        subjectNamesTraversed = new HashSet<GeneralNameInterface>();
13973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        traversedCACerts = 0;
14073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
14173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        /*
14273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root         * Populate forwardCheckers with every user-defined checker
14373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root         * that supports forward checking and initialize the forwardCheckers
14473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root         */
14573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        forwardCheckers = new ArrayList<PKIXCertPathChecker>();
14673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        for (PKIXCertPathChecker checker : certPathCheckers) {
14773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            if (checker.isForwardCheckingSupported()) {
14873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                checker.init(true);
14973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                forwardCheckers.add(checker);
15073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            }
15173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        }
15273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
15373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        init = true;
15473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    }
15573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
15673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /**
15773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * Update the state with the next certificate added to the path.
15873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     *
15973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * @param cert the certificate which is used to update the state
16073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
16173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    @Override
16273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    public void updateState(X509Certificate cert)
16373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        throws CertificateException, IOException, CertPathValidatorException {
16473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
16573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        if (cert == null)
16673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            return;
16773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
16873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        X509CertImpl icert = X509CertImpl.toImpl(cert);
16973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
17073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        /* see if certificate key has null parameters */
17173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        if (PKIX.isDSAPublicKeyWithoutParams(icert.getPublicKey())) {
17273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            keyParamsNeededFlag = true;
17373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        }
17473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
17573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        /* update certificate */
17673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        this.cert = icert;
17773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
17873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        /* update issuer DN */
17973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        issuerDN = cert.getIssuerX500Principal();
18073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
18173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        if (!X509CertImpl.isSelfIssued(cert)) {
18273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
18373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            /*
18473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root             * update traversedCACerts only if this is a non-self-issued
18573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root             * intermediate CA cert
18673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root             */
18773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            if (!init && cert.getBasicConstraints() != -1) {
18873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                traversedCACerts++;
18973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            }
19073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        }
19173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
19273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        /* update subjectNamesTraversed only if this is the EE cert or if
19373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root           this cert is not self-issued */
19473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        if (init || !X509CertImpl.isSelfIssued(cert)){
19573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            X500Principal subjName = cert.getSubjectX500Principal();
19673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            subjectNamesTraversed.add(X500Name.asX500Name(subjName));
19773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
19873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            try {
19973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                SubjectAlternativeNameExtension subjAltNameExt
20073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                    = icert.getSubjectAlternativeNameExtension();
20173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                if (subjAltNameExt != null) {
20273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                    GeneralNames gNames = subjAltNameExt.get(
20373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                            SubjectAlternativeNameExtension.SUBJECT_NAME);
20473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                    for (GeneralName gName : gNames.names()) {
20573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                        subjectNamesTraversed.add(gName.getName());
20673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                    }
20773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                }
20873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            } catch (IOException e) {
20973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                if (debug != null) {
21073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                    debug.println("ForwardState.updateState() unexpected "
21173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                        + "exception");
21273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                    e.printStackTrace();
21373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                }
21473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                throw new CertPathValidatorException(e);
21573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            }
21673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        }
21773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
21873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        init = false;
21973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    }
22073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
22173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    /*
22273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * Clone current state. The state is cloned as each cert is
22373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * added to the path. This is necessary if backtracking occurs,
22473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * and a prior state needs to be restored.
22573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     *
22673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * Note that this is a SMART clone. Not all fields are fully copied,
22773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * because some of them will
22873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     * not have their contents modified by subsequent calls to updateState.
22973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root     */
23073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    @Override
23173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
23273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    public Object clone() {
23373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        try {
23473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            ForwardState clonedState = (ForwardState) super.clone();
23573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
23673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            /* clone checkers, if cloneable */
23773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            clonedState.forwardCheckers = (ArrayList<PKIXCertPathChecker>)
23873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                                                forwardCheckers.clone();
23973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            ListIterator<PKIXCertPathChecker> li =
24073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                                clonedState.forwardCheckers.listIterator();
24173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            while (li.hasNext()) {
24273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                PKIXCertPathChecker checker = li.next();
24373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                if (checker instanceof Cloneable) {
24473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                    li.set((PKIXCertPathChecker)checker.clone());
24573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                }
24673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            }
24773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root
24873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            /*
24973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root             * Shallow copy traversed names. There is no need to
25073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root             * deep copy contents, since the elements of the Set
25173405ff8729cca39da90b2e2f604062e323f6f7aKenny Root             * are never modified by subsequent calls to updateState().
25273405ff8729cca39da90b2e2f604062e323f6f7aKenny Root             */
25373405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            clonedState.subjectNamesTraversed
25473405ff8729cca39da90b2e2f604062e323f6f7aKenny Root                = (HashSet<GeneralNameInterface>)subjectNamesTraversed.clone();
25573405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            return clonedState;
25673405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        } catch (CloneNotSupportedException e) {
25773405ff8729cca39da90b2e2f604062e323f6f7aKenny Root            throw new InternalError(e.toString(), e);
25873405ff8729cca39da90b2e2f604062e323f6f7aKenny Root        }
25973405ff8729cca39da90b2e2f604062e323f6f7aKenny Root    }
26073405ff8729cca39da90b2e2f604062e323f6f7aKenny Root}
261