author | weijun |
Wed, 01 Aug 2018 13:35:08 +0800 | |
changeset 51272 | 9d92ff04a29c |
parent 47866 | 39db80b32b69 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
26967
c182469301ee
8037550: Update RFC references in javadoc to RFC 5280
juh
parents:
25859
diff
changeset
|
2 |
* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 24 |
*/ |
25 |
||
26 |
package sun.security.provider.certpath; |
|
27 |
||
28 |
import java.util.Collections; |
|
29 |
import java.util.HashSet; |
|
30 |
import java.util.Iterator; |
|
31 |
import java.util.Set; |
|
32 |
||
33 |
import java.security.cert.*; |
|
34 |
||
35 |
/** |
|
36 |
* Implements the <code>PolicyNode</code> interface. |
|
37 |
* <p> |
|
38 |
* This class provides an implementation of the <code>PolicyNode</code> |
|
39 |
* interface, and is used internally to build and search Policy Trees. |
|
40 |
* While the implementation is mutable during construction, it is immutable |
|
41 |
* before returning to a client and no mutable public or protected methods |
|
42 |
* are exposed by this implementation, as per the contract of PolicyNode. |
|
43 |
* |
|
44 |
* @since 1.4 |
|
45 |
* @author Seth Proctor |
|
46 |
* @author Sean Mullan |
|
47 |
*/ |
|
48 |
final class PolicyNodeImpl implements PolicyNode { |
|
49 |
||
50 |
/** |
|
51 |
* Use to specify the special policy "Any Policy" |
|
52 |
*/ |
|
53 |
private static final String ANY_POLICY = "2.5.29.32.0"; |
|
54 |
||
55 |
// every node has one parent, and zero or more children |
|
56 |
private PolicyNodeImpl mParent; |
|
57 |
private HashSet<PolicyNodeImpl> mChildren; |
|
58 |
||
26967
c182469301ee
8037550: Update RFC references in javadoc to RFC 5280
juh
parents:
25859
diff
changeset
|
59 |
// the 4 fields specified by RFC 5280 |
2 | 60 |
private String mValidPolicy; |
61 |
private HashSet<PolicyQualifierInfo> mQualifierSet; |
|
62 |
private boolean mCriticalityIndicator; |
|
63 |
private HashSet<String> mExpectedPolicySet; |
|
64 |
private boolean mOriginalExpectedPolicySet; |
|
65 |
||
66 |
// the tree depth |
|
67 |
private int mDepth; |
|
68 |
// immutability flag |
|
69 |
private boolean isImmutable = false; |
|
70 |
||
71 |
/** |
|
72 |
* Constructor which takes a <code>PolicyNodeImpl</code> representing the |
|
73 |
* parent in the Policy Tree to this node. If null, this is the |
|
74 |
* root of the tree. The constructor also takes the associated data |
|
75 |
* for this node, as found in the certificate. It also takes a boolean |
|
76 |
* argument specifying whether this node is being created as a result |
|
77 |
* of policy mapping. |
|
78 |
* |
|
79 |
* @param parent the PolicyNode above this in the tree, or null if this |
|
80 |
* node is the tree's root node |
|
81 |
* @param validPolicy a String representing this node's valid policy OID |
|
82 |
* @param qualifierSet the Set of qualifiers for this policy |
|
83 |
* @param criticalityIndicator a boolean representing whether or not the |
|
84 |
* extension is critical |
|
85 |
* @param expectedPolicySet a Set of expected policies |
|
86 |
* @param generatedByPolicyMapping a boolean indicating whether this |
|
87 |
* node was generated by a policy mapping |
|
88 |
*/ |
|
89 |
PolicyNodeImpl(PolicyNodeImpl parent, String validPolicy, |
|
90 |
Set<PolicyQualifierInfo> qualifierSet, |
|
91 |
boolean criticalityIndicator, Set<String> expectedPolicySet, |
|
92 |
boolean generatedByPolicyMapping) { |
|
93 |
mParent = parent; |
|
94 |
mChildren = new HashSet<PolicyNodeImpl>(); |
|
95 |
||
96 |
if (validPolicy != null) |
|
97 |
mValidPolicy = validPolicy; |
|
98 |
else |
|
99 |
mValidPolicy = ""; |
|
100 |
||
101 |
if (qualifierSet != null) |
|
102 |
mQualifierSet = new HashSet<PolicyQualifierInfo>(qualifierSet); |
|
103 |
else |
|
104 |
mQualifierSet = new HashSet<PolicyQualifierInfo>(); |
|
105 |
||
106 |
mCriticalityIndicator = criticalityIndicator; |
|
107 |
||
108 |
if (expectedPolicySet != null) |
|
109 |
mExpectedPolicySet = new HashSet<String>(expectedPolicySet); |
|
110 |
else |
|
111 |
mExpectedPolicySet = new HashSet<String>(); |
|
112 |
||
113 |
mOriginalExpectedPolicySet = !generatedByPolicyMapping; |
|
114 |
||
115 |
// see if we're the root, and act appropriately |
|
116 |
if (mParent != null) { |
|
117 |
mDepth = mParent.getDepth() + 1; |
|
118 |
mParent.addChild(this); |
|
119 |
} else { |
|
120 |
mDepth = 0; |
|
121 |
} |
|
122 |
} |
|
123 |
||
124 |
/** |
|
125 |
* Alternate constructor which makes a new node with the policy data |
|
126 |
* in an existing <code>PolicyNodeImpl</code>. |
|
127 |
* |
|
128 |
* @param parent a PolicyNode that's the new parent of the node, or |
|
129 |
* null if this is the root node |
|
130 |
* @param node a PolicyNode containing the policy data to copy |
|
131 |
*/ |
|
132 |
PolicyNodeImpl(PolicyNodeImpl parent, PolicyNodeImpl node) { |
|
133 |
this(parent, node.mValidPolicy, node.mQualifierSet, |
|
134 |
node.mCriticalityIndicator, node.mExpectedPolicySet, false); |
|
135 |
} |
|
136 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
137 |
@Override |
2 | 138 |
public PolicyNode getParent() { |
139 |
return mParent; |
|
140 |
} |
|
141 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
142 |
@Override |
2 | 143 |
public Iterator<PolicyNodeImpl> getChildren() { |
144 |
return Collections.unmodifiableSet(mChildren).iterator(); |
|
145 |
} |
|
146 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
147 |
@Override |
2 | 148 |
public int getDepth() { |
149 |
return mDepth; |
|
150 |
} |
|
151 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
152 |
@Override |
2 | 153 |
public String getValidPolicy() { |
154 |
return mValidPolicy; |
|
155 |
} |
|
156 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
157 |
@Override |
2 | 158 |
public Set<PolicyQualifierInfo> getPolicyQualifiers() { |
159 |
return Collections.unmodifiableSet(mQualifierSet); |
|
160 |
} |
|
161 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
162 |
@Override |
2 | 163 |
public Set<String> getExpectedPolicies() { |
164 |
return Collections.unmodifiableSet(mExpectedPolicySet); |
|
165 |
} |
|
166 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
167 |
@Override |
2 | 168 |
public boolean isCritical() { |
169 |
return mCriticalityIndicator; |
|
170 |
} |
|
171 |
||
172 |
/** |
|
173 |
* Return a printable representation of the PolicyNode. |
|
174 |
* Starting at the node on which this method is called, |
|
175 |
* it recurses through the tree and prints out each node. |
|
176 |
* |
|
177 |
* @return a String describing the contents of the Policy Node |
|
178 |
*/ |
|
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
179 |
@Override |
2 | 180 |
public String toString() { |
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
181 |
StringBuilder buffer = new StringBuilder(this.asString()); |
2 | 182 |
|
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
183 |
for (PolicyNodeImpl node : mChildren) { |
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
184 |
buffer.append(node); |
2 | 185 |
} |
186 |
return buffer.toString(); |
|
187 |
} |
|
188 |
||
189 |
// private methods and package private operations |
|
190 |
||
191 |
boolean isImmutable() { |
|
192 |
return isImmutable; |
|
193 |
} |
|
194 |
||
195 |
/** |
|
196 |
* Sets the immutability flag of this node and all of its children |
|
197 |
* to true. |
|
198 |
*/ |
|
199 |
void setImmutable() { |
|
200 |
if (isImmutable) |
|
201 |
return; |
|
202 |
for (PolicyNodeImpl node : mChildren) { |
|
203 |
node.setImmutable(); |
|
204 |
} |
|
205 |
isImmutable = true; |
|
206 |
} |
|
207 |
||
208 |
/** |
|
209 |
* Private method sets a child node. This is called from the child's |
|
210 |
* constructor. |
|
211 |
* |
|
212 |
* @param child new <code>PolicyNodeImpl</code> child node |
|
213 |
*/ |
|
214 |
private void addChild(PolicyNodeImpl child) { |
|
215 |
if (isImmutable) { |
|
216 |
throw new IllegalStateException("PolicyNode is immutable"); |
|
217 |
} |
|
218 |
mChildren.add(child); |
|
219 |
} |
|
220 |
||
221 |
/** |
|
222 |
* Adds an expectedPolicy to the expected policy set. |
|
223 |
* If this is the original expected policy set initialized |
|
224 |
* by the constructor, then the expected policy set is cleared |
|
225 |
* before the expected policy is added. |
|
226 |
* |
|
227 |
* @param expectedPolicy a String representing an expected policy. |
|
228 |
*/ |
|
229 |
void addExpectedPolicy(String expectedPolicy) { |
|
230 |
if (isImmutable) { |
|
231 |
throw new IllegalStateException("PolicyNode is immutable"); |
|
232 |
} |
|
233 |
if (mOriginalExpectedPolicySet) { |
|
234 |
mExpectedPolicySet.clear(); |
|
235 |
mOriginalExpectedPolicySet = false; |
|
236 |
} |
|
237 |
mExpectedPolicySet.add(expectedPolicy); |
|
238 |
} |
|
239 |
||
240 |
/** |
|
241 |
* Removes all paths which don't reach the specified depth. |
|
242 |
* |
|
243 |
* @param depth an int representing the desired minimum depth of all paths |
|
244 |
*/ |
|
245 |
void prune(int depth) { |
|
246 |
if (isImmutable) |
|
247 |
throw new IllegalStateException("PolicyNode is immutable"); |
|
248 |
||
249 |
// if we have no children, we can't prune below us... |
|
250 |
if (mChildren.size() == 0) |
|
251 |
return; |
|
252 |
||
253 |
Iterator<PolicyNodeImpl> it = mChildren.iterator(); |
|
254 |
while (it.hasNext()) { |
|
255 |
PolicyNodeImpl node = it.next(); |
|
256 |
node.prune(depth); |
|
257 |
// now that we've called prune on the child, see if we should |
|
258 |
// remove it from the tree |
|
259 |
if ((node.mChildren.size() == 0) && (depth > mDepth + 1)) |
|
260 |
it.remove(); |
|
261 |
} |
|
262 |
} |
|
263 |
||
264 |
/** |
|
265 |
* Deletes the specified child node of this node, if it exists. |
|
266 |
* |
|
267 |
* @param childNode the child node to be deleted |
|
268 |
*/ |
|
269 |
void deleteChild(PolicyNode childNode) { |
|
270 |
if (isImmutable) { |
|
271 |
throw new IllegalStateException("PolicyNode is immutable"); |
|
272 |
} |
|
273 |
mChildren.remove(childNode); |
|
274 |
} |
|
275 |
||
276 |
/** |
|
277 |
* Returns a copy of the tree, without copying the policy-related data, |
|
278 |
* rooted at the node on which this was called. |
|
279 |
* |
|
280 |
* @return a copy of the tree |
|
281 |
*/ |
|
282 |
PolicyNodeImpl copyTree() { |
|
283 |
return copyTree(null); |
|
284 |
} |
|
285 |
||
286 |
private PolicyNodeImpl copyTree(PolicyNodeImpl parent) { |
|
287 |
PolicyNodeImpl newNode = new PolicyNodeImpl(parent, this); |
|
288 |
||
289 |
for (PolicyNodeImpl node : mChildren) { |
|
290 |
node.copyTree(newNode); |
|
291 |
} |
|
292 |
||
293 |
return newNode; |
|
294 |
} |
|
295 |
||
296 |
/** |
|
297 |
* Returns all nodes at the specified depth in the tree. |
|
298 |
* |
|
299 |
* @param depth an int representing the depth of the desired nodes |
|
300 |
* @return a <code>Set</code> of all nodes at the specified depth |
|
301 |
*/ |
|
302 |
Set<PolicyNodeImpl> getPolicyNodes(int depth) { |
|
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
303 |
Set<PolicyNodeImpl> set = new HashSet<>(); |
2 | 304 |
getPolicyNodes(depth, set); |
305 |
return set; |
|
306 |
} |
|
307 |
||
308 |
/** |
|
47866
39db80b32b69
8191632: Typos in comments due to duplicating words
igerasim
parents:
47216
diff
changeset
|
309 |
* Add all nodes at depth to set and return the Set. |
2 | 310 |
* Internal recursion helper. |
311 |
*/ |
|
312 |
private void getPolicyNodes(int depth, Set<PolicyNodeImpl> set) { |
|
313 |
// if we've reached the desired depth, then return ourself |
|
314 |
if (mDepth == depth) { |
|
315 |
set.add(this); |
|
316 |
} else { |
|
317 |
for (PolicyNodeImpl node : mChildren) { |
|
318 |
node.getPolicyNodes(depth, set); |
|
319 |
} |
|
320 |
} |
|
321 |
} |
|
322 |
||
323 |
/** |
|
324 |
* Finds all nodes at the specified depth whose expected_policy_set |
|
325 |
* contains the specified expected OID (if matchAny is false) |
|
326 |
* or the special OID "any value" (if matchAny is true). |
|
327 |
* |
|
328 |
* @param depth an int representing the desired depth |
|
329 |
* @param expectedOID a String encoding the valid OID to match |
|
330 |
* @param matchAny a boolean indicating whether an expected_policy_set |
|
331 |
* containing ANY_POLICY should be considered a match |
|
332 |
* @return a Set of matched <code>PolicyNode</code>s |
|
333 |
*/ |
|
334 |
Set<PolicyNodeImpl> getPolicyNodesExpected(int depth, |
|
335 |
String expectedOID, boolean matchAny) { |
|
336 |
||
337 |
if (expectedOID.equals(ANY_POLICY)) { |
|
338 |
return getPolicyNodes(depth); |
|
339 |
} else { |
|
340 |
return getPolicyNodesExpectedHelper(depth, expectedOID, matchAny); |
|
341 |
} |
|
342 |
} |
|
343 |
||
344 |
private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth, |
|
345 |
String expectedOID, boolean matchAny) { |
|
346 |
||
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
347 |
HashSet<PolicyNodeImpl> set = new HashSet<>(); |
2 | 348 |
|
349 |
if (mDepth < depth) { |
|
350 |
for (PolicyNodeImpl node : mChildren) { |
|
351 |
set.addAll(node.getPolicyNodesExpectedHelper(depth, |
|
352 |
expectedOID, |
|
353 |
matchAny)); |
|
354 |
} |
|
355 |
} else { |
|
356 |
if (matchAny) { |
|
357 |
if (mExpectedPolicySet.contains(ANY_POLICY)) |
|
358 |
set.add(this); |
|
359 |
} else { |
|
360 |
if (mExpectedPolicySet.contains(expectedOID)) |
|
361 |
set.add(this); |
|
362 |
} |
|
363 |
} |
|
364 |
||
365 |
return set; |
|
366 |
} |
|
367 |
||
368 |
/** |
|
369 |
* Finds all nodes at the specified depth that contains the |
|
370 |
* specified valid OID |
|
371 |
* |
|
372 |
* @param depth an int representing the desired depth |
|
373 |
* @param validOID a String encoding the valid OID to match |
|
374 |
* @return a Set of matched <code>PolicyNode</code>s |
|
375 |
*/ |
|
376 |
Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) { |
|
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
377 |
HashSet<PolicyNodeImpl> set = new HashSet<>(); |
2 | 378 |
|
379 |
if (mDepth < depth) { |
|
380 |
for (PolicyNodeImpl node : mChildren) { |
|
381 |
set.addAll(node.getPolicyNodesValid(depth, validOID)); |
|
382 |
} |
|
383 |
} else { |
|
384 |
if (mValidPolicy.equals(validOID)) |
|
385 |
set.add(this); |
|
386 |
} |
|
387 |
||
388 |
return set; |
|
389 |
} |
|
390 |
||
391 |
private static String policyToString(String oid) { |
|
392 |
if (oid.equals(ANY_POLICY)) { |
|
393 |
return "anyPolicy"; |
|
394 |
} else { |
|
395 |
return oid; |
|
396 |
} |
|
397 |
} |
|
398 |
||
399 |
/** |
|
400 |
* Prints out some data on this node. |
|
401 |
*/ |
|
402 |
String asString() { |
|
403 |
if (mParent == null) { |
|
404 |
return "anyPolicy ROOT\n"; |
|
405 |
} else { |
|
12860
9ffbd4e43413
6854712: Revocation checking enhancements (JEP-124)
mullan
parents:
5506
diff
changeset
|
406 |
StringBuilder sb = new StringBuilder(); |
2 | 407 |
for (int i = 0, n = getDepth(); i < n; i++) { |
408 |
sb.append(" "); |
|
409 |
} |
|
410 |
sb.append(policyToString(getValidPolicy())); |
|
411 |
sb.append(" CRIT: "); |
|
412 |
sb.append(isCritical()); |
|
413 |
sb.append(" EP: "); |
|
414 |
for (String policy : getExpectedPolicies()) { |
|
415 |
sb.append(policyToString(policy)); |
|
416 |
sb.append(" "); |
|
417 |
} |
|
418 |
sb.append(" ("); |
|
419 |
sb.append(getDepth()); |
|
420 |
sb.append(")\n"); |
|
421 |
return sb.toString(); |
|
422 |
} |
|
423 |
} |
|
424 |
} |