History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/x509/GeneralSubtrees.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/x509/GeneralSubtrees.java+525−0
@@ -0,0 +1,525 @@
1/*
2 * Copyright (c) 1997, 2003, 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
26package sun.security.x509;
27
28import java.io.*;
29import java.util.*;
30
31import sun.security.util.*;
32
33/**
34 * Represent the GeneralSubtrees ASN.1 object.
35 * <p>
36 * The ASN.1 for this is
37 * <pre>
38 * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
39 * </pre>
40 * </p>
41 *
42 *
43 * @author Amit Kapoor
44 * @author Hemma Prafullchandra
45 * @author Andreas Sterbenz
46 */
47public class GeneralSubtrees implements Cloneable {
48
49 private final List<GeneralSubtree> trees;
50
51 // Private variables
52 private static final int NAME_DIFF_TYPE = GeneralNameInterface.NAME_DIFF_TYPE;
53 private static final int NAME_MATCH = GeneralNameInterface.NAME_MATCH;
54 private static final int NAME_NARROWS = GeneralNameInterface.NAME_NARROWS;
55 private static final int NAME_WIDENS = GeneralNameInterface.NAME_WIDENS;
56 private static final int NAME_SAME_TYPE = GeneralNameInterface.NAME_SAME_TYPE;
57
58 /**
59 * The default constructor for the class.
60 */
61 public GeneralSubtrees() {
62 trees = new ArrayList<GeneralSubtree>();
63 }
64
65 private GeneralSubtrees(GeneralSubtrees source) {
66 trees = new ArrayList<GeneralSubtree>(source.trees);
67 }
68
69 /**
70 * Create the object from the passed DER encoded form.
71 *
72 * @param val the DER encoded form of the same.
73 */
74 public GeneralSubtrees(DerValue val) throws IOException {
75 this();
76 if (val.tag != DerValue.tag_Sequence) {
77 throw new IOException("Invalid encoding of GeneralSubtrees.");
78 }
79 while (val.data.available() != 0) {
80 DerValue opt = val.data.getDerValue();
81 GeneralSubtree tree = new GeneralSubtree(opt);
82 add(tree);
83 }
84 }
85
86 public GeneralSubtree get(int index) {
87 return trees.get(index);
88 }
89
90 public void remove(int index) {
91 trees.remove(index);
92 }
93
94 public void add(GeneralSubtree tree) {
95 if (tree == null) {
96 throw new NullPointerException();
97 }
98 trees.add(tree);
99 }
100
101 public boolean contains(GeneralSubtree tree) {
102 if (tree == null) {
103 throw new NullPointerException();
104 }
105 return trees.contains(tree);
106 }
107
108 public int size() {
109 return trees.size();
110 }
111
112 public Iterator<GeneralSubtree> iterator() {
113 return trees.iterator();
114 }
115
116 public List<GeneralSubtree> trees() {
117 return trees;
118 }
119
120 public Object clone() {
121 return new GeneralSubtrees(this);
122 }
123
124 /**
125 * Return a printable string of the GeneralSubtree.
126 */
127 public String toString() {
128 String s = " GeneralSubtrees:\n" + trees.toString() + "\n";
129 return s;
130 }
131
132 /**
133 * Encode the GeneralSubtrees.
134 *
135 * @params out the DerOutputStrean to encode this object to.
136 */
137 public void encode(DerOutputStream out) throws IOException {
138 DerOutputStream seq = new DerOutputStream();
139
140 for (int i = 0, n = size(); i < n; i++) {
141 get(i).encode(seq);
142 }
143 out.write(DerValue.tag_Sequence, seq);
144 }
145
146 /**
147 * Compare two general subtrees by comparing the subtrees
148 * of each.
149 *
150 * @param other GeneralSubtrees to compare to this
151 * @returns true if match
152 */
153 public boolean equals(Object obj) {
154 if (this == obj) {
155 return true;
156 }
157 if (obj instanceof GeneralSubtrees == false) {
158 return false;
159 }
160 GeneralSubtrees other = (GeneralSubtrees)obj;
161 return this.trees.equals(other.trees);
162 }
163
164 public int hashCode() {
165 return trees.hashCode();
166 }
167
168 /**
169 * Return the GeneralNameInterface form of the GeneralName in one of
170 * the GeneralSubtrees.
171 *
172 * @param ndx index of the GeneralSubtree from which to obtain the name
173 */
174 private GeneralNameInterface getGeneralNameInterface(int ndx) {
175 return getGeneralNameInterface(get(ndx));
176 }
177
178 private static GeneralNameInterface getGeneralNameInterface(GeneralSubtree gs) {
179 GeneralName gn = gs.getName();
180 GeneralNameInterface gni = gn.getName();
181 return gni;
182 }
183
184 /**
185 * minimize this GeneralSubtrees by removing all redundant entries.
186 * Internal method used by intersect and reduce.
187 */
188 private void minimize() {
189
190 // Algorithm: compare each entry n to all subsequent entries in
191 // the list: if any subsequent entry matches or widens entry n,
192 // remove entry n. If any subsequent entries narrow entry n, remove
193 // the subsequent entries.
194 for (int i = 0; i < size(); i++) {
195 GeneralNameInterface current = getGeneralNameInterface(i);
196 boolean remove1 = false;
197
198 /* compare current to subsequent elements */
199 for (int j = i + 1; j < size(); j++) {
200 GeneralNameInterface subsequent = getGeneralNameInterface(j);
201 switch (current.constrains(subsequent)) {
202 case GeneralNameInterface.NAME_DIFF_TYPE:
203 /* not comparable; different name types; keep checking */
204 continue;
205 case GeneralNameInterface.NAME_MATCH:
206 /* delete one of the duplicates */
207 remove1 = true;
208 break;
209 case GeneralNameInterface.NAME_NARROWS:
210 /* subsequent narrows current */
211 /* remove narrower name (subsequent) */
212 remove(j);
213 j--; /* continue check with new subsequent */
214 continue;
215 case GeneralNameInterface.NAME_WIDENS:
216 /* subsequent widens current */
217 /* remove narrower name current */
218 remove1 = true;
219 break;
220 case GeneralNameInterface.NAME_SAME_TYPE:
221 /* keep both for now; keep checking */
222 continue;
223 }
224 break;
225 } /* end of this pass of subsequent elements */
226
227 if (remove1) {
228 remove(i);
229 i--; /* check the new i value */
230 }
231
232 }
233 }
234
235 /**
236 * create a subtree containing an instance of the input
237 * name type that widens all other names of that type.
238 *
239 * @params name GeneralNameInterface name
240 * @returns GeneralSubtree containing widest name of that type
241 * @throws RuntimeException on error (should not occur)
242 */
243 private GeneralSubtree createWidestSubtree(GeneralNameInterface name) {
244 try {
245 GeneralName newName;
246 switch (name.getType()) {
247 case GeneralNameInterface.NAME_ANY:
248 // Create new OtherName with same OID as baseName, but
249 // empty value
250 ObjectIdentifier otherOID = ((OtherName)name).getOID();
251 newName = new GeneralName(new OtherName(otherOID, null));
252 break;
253 case GeneralNameInterface.NAME_RFC822:
254 newName = new GeneralName(new RFC822Name(""));
255 break;
256 case GeneralNameInterface.NAME_DNS:
257 newName = new GeneralName(new DNSName(""));
258 break;
259 case GeneralNameInterface.NAME_X400:
260 newName = new GeneralName(new X400Address((byte[])null));
261 break;
262 case GeneralNameInterface.NAME_DIRECTORY:
263 newName = new GeneralName(new X500Name(""));
264 break;
265 case GeneralNameInterface.NAME_EDI:
266 newName = new GeneralName(new EDIPartyName(""));
267 break;
268 case GeneralNameInterface.NAME_URI:
269 newName = new GeneralName(new URIName(""));
270 break;
271 case GeneralNameInterface.NAME_IP:
272 newName = new GeneralName(new IPAddressName((byte[])null));
273 break;
274 case GeneralNameInterface.NAME_OID:
275 newName = new GeneralName
276 (new OIDName(new ObjectIdentifier((int[])null)));
277 break;
278 default:
279 throw new IOException
280 ("Unsupported GeneralNameInterface type: " + name.getType());
281 }
282 return new GeneralSubtree(newName, 0, -1);
283 } catch (IOException e) {
284 throw new RuntimeException("Unexpected error: " + e, e);
285 }
286 }
287
288 /**
289 * intersect this GeneralSubtrees with other. This function
290 * is used in merging permitted NameConstraints. The operation
291 * is performed as follows:
292 * <ul>
293 * <li>If a name in other narrows all names of the same type in this,
294 * the result will contain the narrower name and none of the
295 * names it narrows.
296 * <li>If a name in other widens all names of the same type in this,
297 * the result will not contain the wider name.
298 * <li>If a name in other does not share the same subtree with any name
299 * of the same type in this, then the name is added to the list
300 * of GeneralSubtrees returned. These names should be added to
301 * the list of names that are specifically excluded. The reason
302 * is that, if the intersection is empty, then no names of that
303 * type are permitted, and the only way to express this in
304 * NameConstraints is to include the name in excludedNames.
305 * <li>If a name in this has no name of the same type in other, then
306 * the result contains the name in this. No name of a given type
307 * means the name type is completely permitted.
308 * <li>If a name in other has no name of the same type in this, then
309 * the result contains the name in other. This means that
310 * the name is now constrained in some way, whereas before it was
311 * completely permitted.
312 * <ul>
313 *
314 * @param other GeneralSubtrees to be intersected with this
315 * @returns GeneralSubtrees to be merged with excluded; these are
316 * empty-valued name types corresponding to entries that were
317 * of the same type but did not share the same subtree between
318 * this and other. Returns null if no such.
319 */
320 public GeneralSubtrees intersect(GeneralSubtrees other) {
321
322 if (other == null) {
323 throw new NullPointerException("other GeneralSubtrees must not be null");
324 }
325
326 GeneralSubtrees newThis = new GeneralSubtrees();
327 GeneralSubtrees newExcluded = null;
328
329 // Step 1: If this is empty, just add everything in other to this and
330 // return no new excluded entries
331 if (size() == 0) {
332 union(other);
333 return null;
334 }
335
336 // Step 2: For ease of checking the subtrees, minimize them by
337 // constructing versions that contain only the widest instance of
338 // each type
339 this.minimize();
340 other.minimize();
341
342 // Step 3: Check each entry in this to see whether we keep it or
343 // remove it, and whether we add anything to newExcluded or newThis.
344 // We keep an entry in this unless it is narrowed by all entries in
345 // other. We add an entry to newExcluded if there is at least one
346 // entry of the same nameType in other, but this entry does
347 // not share the same subtree with any of the entries in other.
348 // We add an entry from other to newThis if there is no name of the
349 // same type in this.
350 for (int i = 0; i < size(); i++) {
351 GeneralNameInterface thisEntry = getGeneralNameInterface(i);
352 boolean removeThisEntry = false;
353
354 // Step 3a: If the widest name of this type in other narrows
355 // thisEntry, remove thisEntry and add widest other to newThis.
356 // Simultaneously, check for situation where there is a name of
357 // this type in other, but no name in other matches, narrows,
358 // or widens thisEntry.
359 boolean sameType = false;
360 for (int j = 0; j < other.size(); j++) {
361 GeneralSubtree otherEntryGS = other.get(j);
362 GeneralNameInterface otherEntry =
363 getGeneralNameInterface(otherEntryGS);
364 switch (thisEntry.constrains(otherEntry)) {
365 case NAME_NARROWS:
366 remove(i);
367 i--;
368 newThis.add(otherEntryGS);
369 sameType = false;
370 break;
371 case NAME_SAME_TYPE:
372 sameType = true;
373 continue;
374 case NAME_MATCH:
375 case NAME_WIDENS:
376 sameType = false;
377 break;
378 case NAME_DIFF_TYPE:
379 default:
380 continue;
381 }
382 break;
383 }
384
385 // Step 3b: If sameType is still true, we have the situation
386 // where there was a name of the same type as thisEntry in
387 // other, but no name in other widened, matched, or narrowed
388 // thisEntry.
389 if (sameType) {
390
391 // Step 3b.1: See if there are any entries in this and other
392 // with this type that match, widen, or narrow each other.
393 // If not, then we need to add a "widest subtree" of this
394 // type to excluded.
395 boolean intersection = false;
396 for (int j = 0; j < size(); j++) {
397 GeneralNameInterface thisAltEntry = getGeneralNameInterface(j);
398
399 if (thisAltEntry.getType() == thisEntry.getType()) {
400 for (int k = 0; k < other.size(); k++) {
401 GeneralNameInterface othAltEntry =
402 other.getGeneralNameInterface(k);
403
404 int constraintType =
405 thisAltEntry.constrains(othAltEntry);
406 if (constraintType == NAME_MATCH ||
407 constraintType == NAME_WIDENS ||
408 constraintType == NAME_NARROWS) {
409 intersection = true;
410 break;
411 }
412 }
413 }
414 }
415 if (intersection == false) {
416 if (newExcluded == null) {
417 newExcluded = new GeneralSubtrees();
418 }
419 GeneralSubtree widestSubtree =
420 createWidestSubtree(thisEntry);
421 if (!newExcluded.contains(widestSubtree)) {
422 newExcluded.add(widestSubtree);
423 }
424 }
425
426 // Step 3b.2: Remove thisEntry from this
427 remove(i);
428 i--;
429 }
430 }
431
432 // Step 4: Add all entries in newThis to this
433 if (newThis.size() > 0) {
434 union(newThis);
435 }
436
437 // Step 5: Add all entries in other that do not have any entry of the
438 // same type in this to this
439 for (int i = 0; i < other.size(); i++) {
440 GeneralSubtree otherEntryGS = other.get(i);
441 GeneralNameInterface otherEntry = getGeneralNameInterface(otherEntryGS);
442 boolean diffType = false;
443 for (int j = 0; j < size(); j++) {
444 GeneralNameInterface thisEntry = getGeneralNameInterface(j);
445 switch (thisEntry.constrains(otherEntry)) {
446 case NAME_DIFF_TYPE:
447 diffType = true;
448 // continue to see if we find something later of the
449 // same type
450 continue;
451 case NAME_NARROWS:
452 case NAME_SAME_TYPE:
453 case NAME_MATCH:
454 case NAME_WIDENS:
455 diffType = false; // we found an entry of the same type
456 // break because we know we won't be adding it to
457 // this now
458 break;
459 default:
460 continue;
461 }
462 break;
463 }
464 if (diffType) {
465 add(otherEntryGS);
466 }
467 }
468
469 // Step 6: Return the newExcluded GeneralSubtrees
470 return newExcluded;
471 }
472
473 /**
474 * construct union of this GeneralSubtrees with other.
475 *
476 * @param other GeneralSubtrees to be united with this
477 */
478 public void union(GeneralSubtrees other) {
479 if (other != null) {
480 for (int i = 0, n = other.size(); i < n; i++) {
481 add(other.get(i));
482 }
483 // Minimize this
484 minimize();
485 }
486 }
487
488 /**
489 * reduce this GeneralSubtrees by contents of another. This function
490 * is used in merging excluded NameConstraints with permitted NameConstraints
491 * to obtain a minimal form of permitted NameConstraints. It is an
492 * optimization, and does not affect correctness of the results.
493 *
494 * @param excluded GeneralSubtrees
495 */
496 public void reduce(GeneralSubtrees excluded) {
497 if (excluded == null) {
498 return;
499 }
500 for (int i = 0, n = excluded.size(); i < n; i++) {
501 GeneralNameInterface excludedName = excluded.getGeneralNameInterface(i);
502 for (int j = 0; j < size(); j++) {
503 GeneralNameInterface permitted = getGeneralNameInterface(j);
504 switch (excludedName.constrains(permitted)) {
505 case GeneralNameInterface.NAME_DIFF_TYPE:
506 break;
507 case GeneralNameInterface.NAME_MATCH:
508 remove(j);
509 j--;
510 break;
511 case GeneralNameInterface.NAME_NARROWS:
512 /* permitted narrows excluded */
513 remove(j);
514 j--;
515 break;
516 case GeneralNameInterface.NAME_WIDENS:
517 /* permitted widens excluded */
518 break;
519 case GeneralNameInterface.NAME_SAME_TYPE:
520 break;
521 }
522 } /* end of this pass of permitted */
523 } /* end of pass of excluded */
524 }
525}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t