1 /*
2  * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.security.provider.certpath;
27 
28 import java.io.IOException;
29 import java.security.cert.CertificateException;
30 import java.security.cert.CertPathValidatorException;
31 import java.security.cert.PKIXCertPathChecker;
32 import java.security.cert.X509Certificate;
33 import java.util.ArrayList;
34 import java.util.HashSet;
35 import java.util.List;
36 import java.util.ListIterator;
37 import javax.security.auth.x500.X500Principal;
38 
39 import sun.security.util.Debug;
40 import sun.security.x509.SubjectAlternativeNameExtension;
41 import sun.security.x509.GeneralNames;
42 import sun.security.x509.GeneralName;
43 import sun.security.x509.GeneralNameInterface;
44 import sun.security.x509.X500Name;
45 import sun.security.x509.X509CertImpl;
46 
47 /**
48  * A specification of a forward PKIX validation state
49  * which is initialized by each build and updated each time a
50  * certificate is added to the current path.
51  * @since       1.4
52  * @author      Yassir Elley
53  */
54 class ForwardState implements State {
55 
56     private static final Debug debug = Debug.getInstance("certpath");
57 
58     /* The issuer DN of the last cert in the path */
59     X500Principal issuerDN;
60 
61     /* The last cert in the path */
62     X509CertImpl cert;
63 
64     /* The set of subjectDNs and subjectAltNames of all certs in the path */
65     HashSet<GeneralNameInterface> subjectNamesTraversed;
66 
67     /*
68      * The number of intermediate CA certs which have been traversed so
69      * far in the path
70      */
71     int traversedCACerts;
72 
73     /* Flag indicating if state is initial (path is just starting) */
74     private boolean init = true;
75 
76 
77     /* the untrusted certificates checker */
78     // Android-removed: Android doesn't use this mechanism for checking untrusted certificates.
79     // UntrustedChecker untrustedChecker;
80 
81     /* The list of user-defined checkers that support forward checking */
82     ArrayList<PKIXCertPathChecker> forwardCheckers;
83 
84     /* Flag indicating if key needing to inherit key parameters has been
85      * encountered.
86      */
87     boolean keyParamsNeededFlag = false;
88 
89     /**
90      * Returns a boolean flag indicating if the state is initial
91      * (just starting)
92      *
93      * @return boolean flag indicating if the state is initial (just starting)
94      */
95     @Override
isInitial()96     public boolean isInitial() {
97         return init;
98     }
99 
100     /**
101      * Return boolean flag indicating whether a public key that needs to inherit
102      * key parameters has been encountered.
103      *
104      * @return boolean true if key needing to inherit parameters has been
105      * encountered; false otherwise.
106      */
107     @Override
keyParamsNeeded()108     public boolean keyParamsNeeded() {
109         return keyParamsNeededFlag;
110     }
111 
112     /**
113      * Display state for debugging purposes
114      */
115     @Override
toString()116     public String toString() {
117         StringBuilder sb = new StringBuilder();
118         sb.append("State [");
119         sb.append("\n  issuerDN of last cert: ").append(issuerDN);
120         sb.append("\n  traversedCACerts: ").append(traversedCACerts);
121         sb.append("\n  init: ").append(String.valueOf(init));
122         sb.append("\n  keyParamsNeeded: ").append
123                  (String.valueOf(keyParamsNeededFlag));
124         sb.append("\n  subjectNamesTraversed: \n").append
125                  (subjectNamesTraversed);
126         sb.append("]\n");
127         return sb.toString();
128     }
129 
130     /**
131      * Initialize the state.
132      *
133      * @param certPathCheckers the list of user-defined PKIXCertPathCheckers
134      */
initState(List<PKIXCertPathChecker> certPathCheckers)135     public void initState(List<PKIXCertPathChecker> certPathCheckers)
136         throws CertPathValidatorException
137     {
138         subjectNamesTraversed = new HashSet<GeneralNameInterface>();
139         traversedCACerts = 0;
140 
141         /*
142          * Populate forwardCheckers with every user-defined checker
143          * that supports forward checking and initialize the forwardCheckers
144          */
145         forwardCheckers = new ArrayList<PKIXCertPathChecker>();
146         for (PKIXCertPathChecker checker : certPathCheckers) {
147             if (checker.isForwardCheckingSupported()) {
148                 checker.init(true);
149                 forwardCheckers.add(checker);
150             }
151         }
152 
153         init = true;
154     }
155 
156     /**
157      * Update the state with the next certificate added to the path.
158      *
159      * @param cert the certificate which is used to update the state
160      */
161     @Override
updateState(X509Certificate cert)162     public void updateState(X509Certificate cert)
163         throws CertificateException, IOException, CertPathValidatorException {
164 
165         if (cert == null)
166             return;
167 
168         X509CertImpl icert = X509CertImpl.toImpl(cert);
169 
170         /* see if certificate key has null parameters */
171         if (PKIX.isDSAPublicKeyWithoutParams(icert.getPublicKey())) {
172             keyParamsNeededFlag = true;
173         }
174 
175         /* update certificate */
176         this.cert = icert;
177 
178         /* update issuer DN */
179         issuerDN = cert.getIssuerX500Principal();
180 
181         if (!X509CertImpl.isSelfIssued(cert)) {
182 
183             /*
184              * update traversedCACerts only if this is a non-self-issued
185              * intermediate CA cert
186              */
187             if (!init && cert.getBasicConstraints() != -1) {
188                 traversedCACerts++;
189             }
190         }
191 
192         /* update subjectNamesTraversed only if this is the EE cert or if
193            this cert is not self-issued */
194         if (init || !X509CertImpl.isSelfIssued(cert)){
195             X500Principal subjName = cert.getSubjectX500Principal();
196             subjectNamesTraversed.add(X500Name.asX500Name(subjName));
197 
198             try {
199                 SubjectAlternativeNameExtension subjAltNameExt
200                     = icert.getSubjectAlternativeNameExtension();
201                 if (subjAltNameExt != null) {
202                     GeneralNames gNames = subjAltNameExt.get(
203                             SubjectAlternativeNameExtension.SUBJECT_NAME);
204                     for (GeneralName gName : gNames.names()) {
205                         subjectNamesTraversed.add(gName.getName());
206                     }
207                 }
208             } catch (IOException e) {
209                 if (debug != null) {
210                     debug.println("ForwardState.updateState() unexpected "
211                         + "exception");
212                     e.printStackTrace();
213                 }
214                 throw new CertPathValidatorException(e);
215             }
216         }
217 
218         init = false;
219     }
220 
221     /*
222      * Clone current state. The state is cloned as each cert is
223      * added to the path. This is necessary if backtracking occurs,
224      * and a prior state needs to be restored.
225      *
226      * Note that this is a SMART clone. Not all fields are fully copied,
227      * because some of them will
228      * not have their contents modified by subsequent calls to updateState.
229      */
230     @Override
231     @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
clone()232     public Object clone() {
233         try {
234             ForwardState clonedState = (ForwardState) super.clone();
235 
236             /* clone checkers, if cloneable */
237             clonedState.forwardCheckers = (ArrayList<PKIXCertPathChecker>)
238                                                 forwardCheckers.clone();
239             ListIterator<PKIXCertPathChecker> li =
240                                 clonedState.forwardCheckers.listIterator();
241             while (li.hasNext()) {
242                 PKIXCertPathChecker checker = li.next();
243                 if (checker instanceof Cloneable) {
244                     li.set((PKIXCertPathChecker)checker.clone());
245                 }
246             }
247 
248             /*
249              * Shallow copy traversed names. There is no need to
250              * deep copy contents, since the elements of the Set
251              * are never modified by subsequent calls to updateState().
252              */
253             clonedState.subjectNamesTraversed
254                 = (HashSet<GeneralNameInterface>)subjectNamesTraversed.clone();
255             return clonedState;
256         } catch (CloneNotSupportedException e) {
257             throw new InternalError(e.toString(), e);
258         }
259     }
260 }
261