0001: package org.bouncycastle.jce.provider;
0002:
0003: import org.bouncycastle.asn1.ASN1OctetString;
0004: import org.bouncycastle.asn1.ASN1Sequence;
0005: import org.bouncycastle.asn1.DERIA5String;
0006: import org.bouncycastle.asn1.x509.GeneralName;
0007: import org.bouncycastle.asn1.x509.GeneralSubtree;
0008: import org.bouncycastle.util.Arrays;
0009: import org.bouncycastle.util.Strings;
0010:
0011: import java.security.cert.CertPathValidatorException;
0012: import java.util.Collection;
0013: import java.util.Collections;
0014: import java.util.HashSet;
0015: import java.util.Iterator;
0016: import java.util.Set;
0017:
0018: public class PKIXNameConstraints {
0019: private Set excludedSubtreesDN = new HashSet();
0020:
0021: private Set excludedSubtreesDNS = new HashSet();
0022:
0023: private Set excludedSubtreesEmail = new HashSet();
0024:
0025: private Set excludedSubtreesURI = new HashSet();
0026:
0027: private Set excludedSubtreesIP = new HashSet();
0028:
0029: private Set permittedSubtreesDN;
0030:
0031: private Set permittedSubtreesDNS;
0032:
0033: private Set permittedSubtreesEmail;
0034:
0035: private Set permittedSubtreesURI;
0036:
0037: private Set permittedSubtreesIP;
0038:
0039: public PKIXNameConstraints() {
0040: }
0041:
0042: private static boolean withinDNSubtree(ASN1Sequence dns,
0043: ASN1Sequence subtree) {
0044: if (subtree.size() < 1) {
0045: return false;
0046: }
0047:
0048: if (subtree.size() > dns.size()) {
0049: return false;
0050: }
0051:
0052: for (int j = subtree.size() - 1; j >= 0; j--) {
0053: if (!subtree.getObjectAt(j).equals(dns.getObjectAt(j))) {
0054: return false;
0055: }
0056: }
0057:
0058: return true;
0059: }
0060:
0061: public void checkPermittedDN(ASN1Sequence dns)
0062: throws CertPathValidatorException {
0063: checkPermittedDN(permittedSubtreesDN, dns);
0064: }
0065:
0066: public void checkExcludedDN(ASN1Sequence dns)
0067: throws CertPathValidatorException {
0068: checkExcludedDN(excludedSubtreesDN, dns);
0069: }
0070:
0071: private void checkPermittedDN(Set permitted, ASN1Sequence dns)
0072: throws CertPathValidatorException {
0073: if (permitted == null) {
0074: return;
0075: }
0076:
0077: Iterator it = permitted.iterator();
0078:
0079: while (it.hasNext()) {
0080: ASN1Sequence subtree = (ASN1Sequence) it.next();
0081:
0082: if (withinDNSubtree(dns, subtree)) {
0083: return;
0084: }
0085: }
0086:
0087: throw new CertPathValidatorException(
0088: "Subject distinguished name is not from a permitted subtree");
0089: }
0090:
0091: private void checkExcludedDN(Set excluded, ASN1Sequence dns)
0092: throws CertPathValidatorException {
0093: if (excluded.isEmpty()) {
0094: return;
0095: }
0096:
0097: Iterator it = excluded.iterator();
0098:
0099: while (it.hasNext()) {
0100: ASN1Sequence subtree = (ASN1Sequence) it.next();
0101:
0102: if (withinDNSubtree(dns, subtree)) {
0103: throw new CertPathValidatorException(
0104: "Subject distinguished name is from an excluded subtree");
0105: }
0106: }
0107: }
0108:
0109: private Set intersectDN(Set permitted, ASN1Sequence dn) {
0110: Set intersect = new HashSet();
0111: if (permitted == null) {
0112: if (dn == null) {
0113: return intersect;
0114: }
0115: intersect.add(dn);
0116: return intersect;
0117: } else {
0118: Iterator _iter = permitted.iterator();
0119: while (_iter.hasNext()) {
0120: ASN1Sequence subtree = (ASN1Sequence) _iter.next();
0121:
0122: if (withinDNSubtree(dn, subtree)) {
0123: intersect.add(dn);
0124: } else if (withinDNSubtree(subtree, dn)) {
0125: intersect.add(subtree);
0126: }
0127: }
0128:
0129: return intersect;
0130: }
0131: }
0132:
0133: private Set unionDN(Set excluded, ASN1Sequence dn) {
0134: if (excluded.isEmpty()) {
0135: if (dn == null) {
0136: return excluded;
0137: }
0138: excluded.add(dn);
0139:
0140: return excluded;
0141: } else {
0142: Set intersect = new HashSet();
0143:
0144: Iterator it = excluded.iterator();
0145: while (it.hasNext()) {
0146: ASN1Sequence subtree = (ASN1Sequence) it.next();
0147:
0148: if (withinDNSubtree(dn, subtree)) {
0149: intersect.add(subtree);
0150: } else if (withinDNSubtree(subtree, dn)) {
0151: intersect.add(dn);
0152: } else {
0153: intersect.add(subtree);
0154: intersect.add(dn);
0155: }
0156: }
0157:
0158: return intersect;
0159: }
0160: }
0161:
0162: private Set intersectEmail(Set permitted, String email) {
0163: Set intersect = new HashSet();
0164: if (permitted == null) {
0165: if (email == null) {
0166: return intersect;
0167: }
0168: intersect.add(email);
0169:
0170: return intersect;
0171: } else {
0172: Iterator it = permitted.iterator();
0173: while (it.hasNext()) {
0174: String _permitted = (String) it.next();
0175:
0176: intersectEmail(email, _permitted, intersect);
0177: }
0178:
0179: return intersect;
0180: }
0181: }
0182:
0183: private Set unionEmail(Set excluded, String email) {
0184: if (excluded.isEmpty()) {
0185: if (email == null) {
0186: return excluded;
0187: }
0188: excluded.add(email);
0189: return excluded;
0190: } else {
0191: Set union = new HashSet();
0192:
0193: Iterator it = excluded.iterator();
0194: while (it.hasNext()) {
0195: String _excluded = (String) it.next();
0196:
0197: unionEmail(_excluded, email, union);
0198: }
0199:
0200: return union;
0201: }
0202: }
0203:
0204: /**
0205: * Returns the intersection of the permitted IP ranges in
0206: * <code>permitted</code> with <code>ip</code>.
0207: *
0208: * @param permitted A <code>Set</code> of permitted IP addresses with
0209: * their subnet mask as byte arrays.
0210: * @param ip The IP address with its subnet mask.
0211: * @return The <code>Set</code> of permitted IP ranges intersected with
0212: * <code>ip</code>.
0213: */
0214: private Set intersectIP(Set permitted, byte[] ip) {
0215: Set intersect = new HashSet();
0216: if (permitted == null) {
0217: if (ip == null) {
0218: return intersect;
0219: }
0220: intersect.add(ip);
0221: return intersect;
0222: } else {
0223: Iterator it = permitted.iterator();
0224: while (it.hasNext()) {
0225: byte[] _permitted = (byte[]) it.next();
0226: intersect.addAll(intersectIPRange(_permitted, ip));
0227: }
0228:
0229: return intersect;
0230: }
0231: }
0232:
0233: /**
0234: * Returns the union of the excluded IP ranges in <code>excluded</code>
0235: * with <code>ip</code>.
0236: *
0237: * @param excluded A <code>Set</code> of excluded IP addresses with their
0238: * subnet mask as byte arrays.
0239: * @param ip The IP address with its subnet mask.
0240: * @return The <code>Set</code> of excluded IP ranges unified with
0241: * <code>ip</code> as byte arrays.
0242: */
0243: private Set unionIP(Set excluded, byte[] ip) {
0244: if (excluded.isEmpty()) {
0245: if (ip == null) {
0246: return excluded;
0247: }
0248: excluded.add(ip);
0249:
0250: return excluded;
0251: } else {
0252: Set union = new HashSet();
0253:
0254: Iterator it = excluded.iterator();
0255: while (it.hasNext()) {
0256: byte[] _excluded = (byte[]) it.next();
0257: union.addAll(unionIPRange(_excluded, ip));
0258: }
0259:
0260: return union;
0261: }
0262: }
0263:
0264: /**
0265: * Calculates the union if two IP ranges.
0266: *
0267: * @param ipWithSubmask1 The first IP address with its subnet mask.
0268: * @param ipWithSubmask2 The second IP address with its subnet mask.
0269: * @return A <code>Set</code> with the union of both addresses.
0270: */
0271: private Set unionIPRange(byte[] ipWithSubmask1,
0272: byte[] ipWithSubmask2) {
0273: Set set = new HashSet();
0274:
0275: // difficult, adding always all IPs is not wrong
0276: if (Arrays.areEqual(ipWithSubmask1, ipWithSubmask2)) {
0277: set.add(ipWithSubmask1);
0278: } else {
0279: set.add(ipWithSubmask1);
0280: set.add(ipWithSubmask2);
0281: }
0282: return set;
0283: }
0284:
0285: /**
0286: * Calculates the interesction if two IP ranges.
0287: *
0288: * @param ipWithSubmask1 The first IP address with its subnet mask.
0289: * @param ipWithSubmask2 The second IP address with its subnet mask.
0290: * @return A <code>Set</code> with the single IP address with its subnet
0291: * mask as a byte array or an empty <code>Set</code>.
0292: */
0293: private Set intersectIPRange(byte[] ipWithSubmask1,
0294: byte[] ipWithSubmask2) {
0295: if (ipWithSubmask1.length != ipWithSubmask2.length) {
0296: return Collections.EMPTY_SET;
0297: }
0298: byte[][] temp = extractIPsAndSubnetMasks(ipWithSubmask1,
0299: ipWithSubmask2);
0300: byte ip1[] = temp[0];
0301: byte subnetmask1[] = temp[1];
0302: byte ip2[] = temp[2];
0303: byte subnetmask2[] = temp[3];
0304:
0305: byte minMax[][] = minMaxIPs(ip1, subnetmask1, ip2, subnetmask2);
0306: byte[] min;
0307: byte[] max;
0308: max = min(minMax[1], minMax[3]);
0309: min = max(minMax[0], minMax[2]);
0310:
0311: // minimum IP address must be bigger than max
0312: if (compareTo(min, max) == 1) {
0313: return Collections.EMPTY_SET;
0314: }
0315: // OR keeps all significant bits
0316: byte[] ip = or(minMax[0], minMax[2]);
0317: byte[] subnetmask = or(subnetmask1, subnetmask2);
0318: return Collections.singleton(ipWithSubnetMask(ip, subnetmask));
0319: }
0320:
0321: /**
0322: * Concatenates the IP address with its subnet mask.
0323: *
0324: * @param ip The IP address.
0325: * @param subnetMask Its subnet mask.
0326: * @return The concatenated IP address with its subnet mask.
0327: */
0328: private byte[] ipWithSubnetMask(byte[] ip, byte[] subnetMask) {
0329: int ipLength = ip.length;
0330: byte[] temp = new byte[ipLength * 2];
0331: System.arraycopy(ip, 0, temp, 0, ipLength);
0332: System.arraycopy(subnetMask, 0, temp, ipLength, ipLength);
0333: return temp;
0334: }
0335:
0336: /**
0337: * Splits the IP addresses and their subnet mask.
0338: *
0339: * @param ipWithSubmask1 The first IP address with the subnet mask.
0340: * @param ipWithSubmask2 The second IP address with the subnet mask.
0341: * @return An array with two elements. Each element contains the IP address
0342: * and the subnet mask in this order.
0343: *
0344: */
0345: private byte[][] extractIPsAndSubnetMasks(byte[] ipWithSubmask1,
0346: byte[] ipWithSubmask2) {
0347: int ipLength = ipWithSubmask1.length / 2;
0348: byte ip1[] = new byte[ipLength];
0349: byte subnetmask1[] = new byte[ipLength];
0350: System.arraycopy(ipWithSubmask1, 0, ip1, 0, ipLength);
0351: System.arraycopy(ipWithSubmask1, ipLength, subnetmask1, 0,
0352: ipLength);
0353:
0354: byte ip2[] = new byte[ipLength];
0355: byte subnetmask2[] = new byte[ipLength];
0356: System.arraycopy(ipWithSubmask2, 0, ip2, 0, ipLength);
0357: System.arraycopy(ipWithSubmask2, ipLength, subnetmask2, 0,
0358: ipLength);
0359: return new byte[][] { ip1, subnetmask1, ip2, subnetmask2 };
0360: }
0361:
0362: /**
0363: * Based on the two IP addresses and their subnet masks the IP range is
0364: * computed for each IP address - subnet mask pair and returned as the
0365: * minimum IP address and the maximum address of the range.
0366: *
0367: * @param ip1 The first IP address.
0368: * @param subnetmask1 The subnet mask of the first IP address.
0369: * @param ip2 The second IP address.
0370: * @param subnetmask2 The subnet mask of the second IP address.
0371: * @return A array with two elements. The first/second element contains the
0372: * min and max IP address of the first/second IP address and its
0373: * subnet mask.
0374: */
0375: private byte[][] minMaxIPs(byte[] ip1, byte[] subnetmask1,
0376: byte[] ip2, byte[] subnetmask2) {
0377: int ipLength = ip1.length;
0378: byte[] min1 = new byte[ipLength];
0379: byte[] max1 = new byte[ipLength];
0380:
0381: byte[] min2 = new byte[ipLength];
0382: byte[] max2 = new byte[ipLength];
0383:
0384: for (int i = 0; i < ipLength; i++) {
0385: min1[i] = (byte) (ip1[i] & subnetmask1[i]);
0386: max1[i] = (byte) (ip1[i] & subnetmask1[i] | ~subnetmask1[i]);
0387:
0388: min2[i] = (byte) (ip2[i] & subnetmask2[i]);
0389: max2[i] = (byte) (ip2[i] & subnetmask2[i] | ~subnetmask2[i]);
0390: }
0391:
0392: return new byte[][] { min1, max1, min2, max2 };
0393: }
0394:
0395: private void checkPermittedEmail(Set permitted, String email)
0396: throws CertPathValidatorException {
0397: if (permitted == null) {
0398: return;
0399: }
0400:
0401: Iterator it = permitted.iterator();
0402:
0403: while (it.hasNext()) {
0404: String str = ((String) it.next());
0405:
0406: if (emailIsConstrained(email, str)) {
0407: return;
0408: }
0409: }
0410:
0411: if (email.length() == 0 && permitted.size() == 0) {
0412: return;
0413: }
0414:
0415: throw new CertPathValidatorException(
0416: "Subject email address is not from a permitted subtree.");
0417: }
0418:
0419: private void checkExcludedEmail(Set excluded, String email)
0420: throws CertPathValidatorException {
0421: if (excluded.isEmpty()) {
0422: return;
0423: }
0424:
0425: Iterator it = excluded.iterator();
0426:
0427: while (it.hasNext()) {
0428: String str = (String) it.next();
0429:
0430: if (emailIsConstrained(email, str)) {
0431: throw new CertPathValidatorException(
0432: "Email address is from an excluded subtree.");
0433: }
0434: }
0435: }
0436:
0437: /**
0438: * Checks if the IP <code>ip</code> is included in the permitted set
0439: * <code>permitted</code>.
0440: *
0441: * @param permitted A <code>Set</code> of permitted IP addresses with
0442: * their subnet mask as byte arrays.
0443: * @param ip The IP address.
0444: * @throws CertPathValidatorException if the IP is not permitted.
0445: */
0446: private void checkPermittedIP(Set permitted, byte[] ip)
0447: throws CertPathValidatorException {
0448: if (permitted == null) {
0449: return;
0450: }
0451:
0452: Iterator it = permitted.iterator();
0453:
0454: while (it.hasNext()) {
0455: byte[] ipWithSubnet = (byte[]) it.next();
0456:
0457: if (isIPConstrained(ip, ipWithSubnet)) {
0458: return;
0459: }
0460: }
0461: if (ip.length == 0 && permitted.size() == 0) {
0462: return;
0463: }
0464: throw new CertPathValidatorException(
0465: "IP is not from a permitted subtree.");
0466: }
0467:
0468: /**
0469: * Checks if the IP <code>ip</code> is included in the excluded set
0470: * <code>excluded</code>.
0471: *
0472: * @param excluded A <code>Set</code> of excluded IP addresses with their
0473: * subnet mask as byte arrays.
0474: * @param ip The IP address.
0475: * @throws CertPathValidatorException if the IP is excluded.
0476: */
0477: private void checkExcludedIP(Set excluded, byte[] ip)
0478: throws CertPathValidatorException {
0479: if (excluded.isEmpty()) {
0480: return;
0481: }
0482:
0483: Iterator it = excluded.iterator();
0484:
0485: while (it.hasNext()) {
0486: byte[] ipWithSubnet = (byte[]) it.next();
0487:
0488: if (isIPConstrained(ip, ipWithSubnet)) {
0489: throw new CertPathValidatorException(
0490: "IP is from an excluded subtree.");
0491: }
0492: }
0493: }
0494:
0495: /**
0496: * Checks if the IP address <code>ip</code> is constrained by
0497: * <code>constraint</code>.
0498: *
0499: * @param ip The IP address.
0500: * @param constraint The constraint. This is an IP address concatenated with
0501: * its subnetmask.
0502: * @return <code>true</code> if constrained, <code>false</code>
0503: * otherwise.
0504: */
0505: private boolean isIPConstrained(byte ip[], byte[] constraint) {
0506: int ipLength = ip.length;
0507:
0508: if (ipLength != (constraint.length / 2)) {
0509: return false;
0510: }
0511:
0512: byte[] subnetMask = new byte[ipLength];
0513: System.arraycopy(constraint, ipLength, subnetMask, 0, ipLength);
0514:
0515: byte[] permittedSubnetAddress = new byte[ipLength];
0516:
0517: byte[] ipSubnetAddress = new byte[ipLength];
0518:
0519: // the resulting IP address by applying the subnet mask
0520: for (int i = 0; i < ipLength; i++) {
0521: permittedSubnetAddress[i] = (byte) (constraint[i] & subnetMask[i]);
0522: ipSubnetAddress[i] = (byte) (ip[i] & subnetMask[i]);
0523: }
0524:
0525: return Arrays.areEqual(permittedSubnetAddress, ipSubnetAddress);
0526: }
0527:
0528: private boolean emailIsConstrained(String email, String constraint) {
0529: String sub = email.substring(email.indexOf('@') + 1);
0530: // a particular mailbox
0531: if (constraint.indexOf('@') != -1) {
0532: if (email.equalsIgnoreCase(constraint)) {
0533: return true;
0534: }
0535: }
0536: // on particular host
0537: else if (!(constraint.charAt(0) == '.')) {
0538: if (sub.equalsIgnoreCase(constraint)) {
0539: return true;
0540: }
0541: }
0542: // address in sub domain
0543: else if (withinDomain(sub, constraint)) {
0544: return true;
0545: }
0546: return false;
0547: }
0548:
0549: private boolean withinDomain(String testDomain, String domain) {
0550: String tempDomain = domain;
0551: if (tempDomain.startsWith(".")) {
0552: tempDomain = tempDomain.substring(1);
0553: }
0554: String[] domainParts = Strings.split(tempDomain, '.');
0555: String[] testDomainParts = Strings.split(testDomain, '.');
0556: // must have at least one subdomain
0557: if (testDomainParts.length <= domainParts.length) {
0558: return false;
0559: }
0560: int d = testDomainParts.length - domainParts.length;
0561: for (int i = -1; i < domainParts.length; i++) {
0562: if (i == -1) {
0563: if (testDomainParts[i + d].equals("")) {
0564: return false;
0565: }
0566: } else if (!domainParts[i]
0567: .equalsIgnoreCase(testDomainParts[i + d])) {
0568: return false;
0569: }
0570: }
0571: return true;
0572: }
0573:
0574: private void checkPermittedDNS(Set permitted, String dns)
0575: throws CertPathValidatorException {
0576: if (permitted == null) {
0577: return;
0578: }
0579:
0580: Iterator it = permitted.iterator();
0581:
0582: while (it.hasNext()) {
0583: String str = ((String) it.next());
0584:
0585: // is sub domain
0586: if (withinDomain(dns, str) || dns.equalsIgnoreCase(str)) {
0587: return;
0588: }
0589: }
0590: if (dns.length() == 0 && permitted.size() == 0) {
0591: return;
0592: }
0593: throw new CertPathValidatorException(
0594: "DNS is not from a permitted subtree.");
0595: }
0596:
0597: private void checkExcludedDNS(Set excluded, String dns)
0598: throws CertPathValidatorException {
0599: if (excluded.isEmpty()) {
0600: return;
0601: }
0602:
0603: Iterator it = excluded.iterator();
0604:
0605: while (it.hasNext()) {
0606: String str = ((String) it.next());
0607:
0608: // is sub domain or the same
0609: if (withinDomain(dns, str) || dns.equalsIgnoreCase(str)) {
0610: throw new CertPathValidatorException(
0611: "DNS is from an excluded subtree.");
0612: }
0613: }
0614: }
0615:
0616: /**
0617: * The common part of <code>email1</code> and <code>email2</code> is
0618: * added to the union <code>union</code>. If <code>email1</code> and
0619: * <code>email2</code> have nothing in common they are added both.
0620: *
0621: * @param email1 Email address constraint 1.
0622: * @param email2 Email address constraint 2.
0623: * @param union The union.
0624: */
0625: private void unionEmail(String email1, String email2, Set union) {
0626: // email1 is a particular address
0627: if (email1.indexOf('@') != -1) {
0628: String _sub = email1.substring(email1.indexOf('@') + 1);
0629: // both are a particular mailbox
0630: if (email2.indexOf('@') != -1) {
0631: if (email1.equalsIgnoreCase(email2)) {
0632: union.add(email1);
0633: } else {
0634: union.add(email1);
0635: union.add(email2);
0636: }
0637: }
0638: // email2 specifies a domain
0639: else if (email2.startsWith(".")) {
0640: if (withinDomain(_sub, email2)) {
0641: union.add(email2);
0642: } else {
0643: union.add(email1);
0644: union.add(email2);
0645: }
0646: }
0647: // email2 specifies a particular host
0648: else {
0649: if (_sub.equalsIgnoreCase(email2)) {
0650: union.add(email2);
0651: } else {
0652: union.add(email1);
0653: union.add(email2);
0654: }
0655: }
0656: }
0657: // email1 specifies a domain
0658: else if (email1.startsWith(".")) {
0659: if (email2.indexOf('@') != -1) {
0660: String _sub = email2.substring(email1.indexOf('@') + 1);
0661: if (withinDomain(_sub, email1)) {
0662: union.add(email1);
0663: } else {
0664: union.add(email1);
0665: union.add(email2);
0666: }
0667: }
0668: // email2 specifies a domain
0669: else if (email2.startsWith(".")) {
0670: if (withinDomain(email1, email2)
0671: || email1.equalsIgnoreCase(email2)) {
0672: union.add(email2);
0673: } else if (withinDomain(email2, email1)) {
0674: union.add(email1);
0675: } else {
0676: union.add(email1);
0677: union.add(email2);
0678: }
0679: } else {
0680: if (withinDomain(email2, email1)) {
0681: union.add(email1);
0682: } else {
0683: union.add(email1);
0684: union.add(email2);
0685: }
0686: }
0687: }
0688: // email specifies a host
0689: else {
0690: if (email2.indexOf('@') != -1) {
0691: String _sub = email2.substring(email1.indexOf('@') + 1);
0692: if (_sub.equalsIgnoreCase(email1)) {
0693: union.add(email1);
0694: } else {
0695: union.add(email1);
0696: union.add(email2);
0697: }
0698: }
0699: // email2 specifies a domain
0700: else if (email2.startsWith(".")) {
0701: if (withinDomain(email1, email2)) {
0702: union.add(email2);
0703: } else {
0704: union.add(email1);
0705: union.add(email2);
0706: }
0707: }
0708: // email2 specifies a particular host
0709: else {
0710: if (email1.equalsIgnoreCase(email2)) {
0711: union.add(email1);
0712: } else {
0713: union.add(email1);
0714: union.add(email2);
0715: }
0716: }
0717: }
0718: }
0719:
0720: private void unionURI(String email1, String email2, Set union) {
0721: // email1 is a particular address
0722: if (email1.indexOf('@') != -1) {
0723: String _sub = email1.substring(email1.indexOf('@') + 1);
0724: // both are a particular mailbox
0725: if (email2.indexOf('@') != -1) {
0726: if (email1.equalsIgnoreCase(email2)) {
0727: union.add(email1);
0728: } else {
0729: union.add(email1);
0730: union.add(email2);
0731: }
0732: }
0733: // email2 specifies a domain
0734: else if (email2.startsWith(".")) {
0735: if (withinDomain(_sub, email2)) {
0736: union.add(email2);
0737: } else {
0738: union.add(email1);
0739: union.add(email2);
0740: }
0741: }
0742: // email2 specifies a particular host
0743: else {
0744: if (_sub.equalsIgnoreCase(email2)) {
0745: union.add(email2);
0746: } else {
0747: union.add(email1);
0748: union.add(email2);
0749: }
0750: }
0751: }
0752: // email1 specifies a domain
0753: else if (email1.startsWith(".")) {
0754: if (email2.indexOf('@') != -1) {
0755: String _sub = email2.substring(email1.indexOf('@') + 1);
0756: if (withinDomain(_sub, email1)) {
0757: union.add(email1);
0758: } else {
0759: union.add(email1);
0760: union.add(email2);
0761: }
0762: }
0763: // email2 specifies a domain
0764: else if (email2.startsWith(".")) {
0765: if (withinDomain(email1, email2)
0766: || email1.equalsIgnoreCase(email2)) {
0767: union.add(email2);
0768: } else if (withinDomain(email2, email1)) {
0769: union.add(email1);
0770: } else {
0771: union.add(email1);
0772: union.add(email2);
0773: }
0774: } else {
0775: if (withinDomain(email2, email1)) {
0776: union.add(email1);
0777: } else {
0778: union.add(email1);
0779: union.add(email2);
0780: }
0781: }
0782: }
0783: // email specifies a host
0784: else {
0785: if (email2.indexOf('@') != -1) {
0786: String _sub = email2.substring(email1.indexOf('@') + 1);
0787: if (_sub.equalsIgnoreCase(email1)) {
0788: union.add(email1);
0789: } else {
0790: union.add(email1);
0791: union.add(email2);
0792: }
0793: }
0794: // email2 specifies a domain
0795: else if (email2.startsWith(".")) {
0796: if (withinDomain(email1, email2)) {
0797: union.add(email2);
0798: } else {
0799: union.add(email1);
0800: union.add(email2);
0801: }
0802: }
0803: // email2 specifies a particular host
0804: else {
0805: if (email1.equalsIgnoreCase(email2)) {
0806: union.add(email1);
0807: } else {
0808: union.add(email1);
0809: union.add(email2);
0810: }
0811: }
0812: }
0813: }
0814:
0815: private Set intersectDNS(Set permitted, String dns) {
0816: Set intersect = new HashSet();
0817: if (permitted == null) {
0818: if (dns == null) {
0819: return intersect;
0820: }
0821: intersect.add(dns);
0822:
0823: return intersect;
0824: } else {
0825: Iterator _iter = permitted.iterator();
0826: while (_iter.hasNext()) {
0827: String _permitted = (String) _iter.next();
0828:
0829: if (withinDomain(_permitted, dns)) {
0830: intersect.add(_permitted);
0831: } else if (withinDomain(dns, _permitted)) {
0832: intersect.add(dns);
0833: }
0834: }
0835:
0836: return intersect;
0837: }
0838: }
0839:
0840: protected Set unionDNS(Set excluded, String dns) {
0841: if (excluded.isEmpty()) {
0842: if (dns == null) {
0843: return excluded;
0844: }
0845: excluded.add(dns);
0846:
0847: return excluded;
0848: } else {
0849: Set union = new HashSet();
0850:
0851: Iterator _iter = excluded.iterator();
0852: while (_iter.hasNext()) {
0853: String _permitted = (String) _iter.next();
0854:
0855: if (withinDomain(_permitted, dns)) {
0856: union.add(dns);
0857: } else if (withinDomain(dns, _permitted)) {
0858: union.add(_permitted);
0859: } else {
0860: union.add(_permitted);
0861: union.add(dns);
0862: }
0863: }
0864:
0865: return union;
0866: }
0867: }
0868:
0869: /**
0870: * The greatest common part <code>email1</code> and <code>email2</code>
0871: * is added to the intersection <code>intersect</code>.
0872: *
0873: * @param email1 Email address constraint 1.
0874: * @param email2 Email address constraint 2.
0875: * @param intersect The intersection.
0876: */
0877: private void intersectEmail(String email1, String email2,
0878: Set intersect) {
0879: // email1 is a particular address
0880: if (email1.indexOf('@') != -1) {
0881: String _sub = email1.substring(email1.indexOf('@') + 1);
0882: // both are a particular mailbox
0883: if (email2.indexOf('@') != -1) {
0884: if (email1.equalsIgnoreCase(email2)) {
0885: intersect.add(email1);
0886: }
0887: }
0888: // email2 specifies a domain
0889: else if (email2.startsWith(".")) {
0890: if (withinDomain(_sub, email2)) {
0891: intersect.add(email1);
0892: }
0893: }
0894: // email2 specifies a particular host
0895: else {
0896: if (_sub.equalsIgnoreCase(email2)) {
0897: intersect.add(email1);
0898: }
0899: }
0900: }
0901: // email specifies a domain
0902: else if (email1.startsWith(".")) {
0903: if (email2.indexOf('@') != -1) {
0904: String _sub = email2.substring(email1.indexOf('@') + 1);
0905: if (withinDomain(_sub, email1)) {
0906: intersect.add(email2);
0907: }
0908: }
0909: // email2 specifies a domain
0910: else if (email2.startsWith(".")) {
0911: if (withinDomain(email1, email2)
0912: || email1.equalsIgnoreCase(email2)) {
0913: intersect.add(email1);
0914: } else if (withinDomain(email2, email1)) {
0915: intersect.add(email2);
0916: }
0917: } else {
0918: if (withinDomain(email2, email1)) {
0919: intersect.add(email2);
0920: }
0921: }
0922: }
0923: // email1 specifies a host
0924: else {
0925: if (email2.indexOf('@') != -1) {
0926: String _sub = email2.substring(email2.indexOf('@') + 1);
0927: if (_sub.equalsIgnoreCase(email1)) {
0928: intersect.add(email2);
0929: }
0930: }
0931: // email2 specifies a domain
0932: else if (email2.startsWith(".")) {
0933: if (withinDomain(email1, email2)) {
0934: intersect.add(email1);
0935: }
0936: }
0937: // email2 specifies a particular host
0938: else {
0939: if (email1.equalsIgnoreCase(email2)) {
0940: intersect.add(email1);
0941: }
0942: }
0943: }
0944: }
0945:
0946: private void checkExcludedURI(Set excluded, String uri)
0947: throws CertPathValidatorException {
0948: if (excluded.isEmpty()) {
0949: return;
0950: }
0951:
0952: Iterator it = excluded.iterator();
0953:
0954: while (it.hasNext()) {
0955: String str = ((String) it.next());
0956:
0957: if (isUriConstrained(uri, str)) {
0958: throw new CertPathValidatorException(
0959: "URI is from an excluded subtree.");
0960: }
0961: }
0962: }
0963:
0964: private Set intersectURI(Set permitted, String uri) {
0965: Set intersect = new HashSet();
0966: if (permitted == null) {
0967: if (uri == null) {
0968: return intersect;
0969: }
0970: intersect.add(uri);
0971:
0972: return intersect;
0973: } else {
0974: Iterator _iter = permitted.iterator();
0975: while (_iter.hasNext()) {
0976: String _permitted = (String) _iter.next();
0977: intersectURI(_permitted, uri, intersect);
0978: }
0979:
0980: return intersect;
0981: }
0982: }
0983:
0984: private Set unionURI(Set excluded, String uri) {
0985: if (excluded.isEmpty()) {
0986: if (uri == null) {
0987: return excluded;
0988: }
0989: excluded.add(uri);
0990:
0991: return excluded;
0992: } else {
0993: Set union = new HashSet();
0994:
0995: Iterator _iter = excluded.iterator();
0996: while (_iter.hasNext()) {
0997: String _excluded = (String) _iter.next();
0998:
0999: unionURI(_excluded, uri, union);
1000: }
1001:
1002: return union;
1003: }
1004: }
1005:
1006: private void intersectURI(String email1, String email2,
1007: Set intersect) {
1008: // email1 is a particular address
1009: if (email1.indexOf('@') != -1) {
1010: String _sub = email1.substring(email1.indexOf('@') + 1);
1011: // both are a particular mailbox
1012: if (email2.indexOf('@') != -1) {
1013: if (email1.equalsIgnoreCase(email2)) {
1014: intersect.add(email1);
1015: }
1016: }
1017: // email2 specifies a domain
1018: else if (email2.startsWith(".")) {
1019: if (withinDomain(_sub, email2)) {
1020: intersect.add(email1);
1021: }
1022: }
1023: // email2 specifies a particular host
1024: else {
1025: if (_sub.equalsIgnoreCase(email2)) {
1026: intersect.add(email1);
1027: }
1028: }
1029: }
1030: // email specifies a domain
1031: else if (email1.startsWith(".")) {
1032: if (email2.indexOf('@') != -1) {
1033: String _sub = email2.substring(email1.indexOf('@') + 1);
1034: if (withinDomain(_sub, email1)) {
1035: intersect.add(email2);
1036: }
1037: }
1038: // email2 specifies a domain
1039: else if (email2.startsWith(".")) {
1040: if (withinDomain(email1, email2)
1041: || email1.equalsIgnoreCase(email2)) {
1042: intersect.add(email1);
1043: } else if (withinDomain(email2, email1)) {
1044: intersect.add(email2);
1045: }
1046: } else {
1047: if (withinDomain(email2, email1)) {
1048: intersect.add(email2);
1049: }
1050: }
1051: }
1052: // email1 specifies a host
1053: else {
1054: if (email2.indexOf('@') != -1) {
1055: String _sub = email2.substring(email2.indexOf('@') + 1);
1056: if (_sub.equalsIgnoreCase(email1)) {
1057: intersect.add(email2);
1058: }
1059: }
1060: // email2 specifies a domain
1061: else if (email2.startsWith(".")) {
1062: if (withinDomain(email1, email2)) {
1063: intersect.add(email1);
1064: }
1065: }
1066: // email2 specifies a particular host
1067: else {
1068: if (email1.equalsIgnoreCase(email2)) {
1069: intersect.add(email1);
1070: }
1071: }
1072: }
1073: }
1074:
1075: private void checkPermittedURI(Set permitted, String uri)
1076: throws CertPathValidatorException {
1077: if (permitted == null) {
1078: return;
1079: }
1080:
1081: Iterator it = permitted.iterator();
1082:
1083: while (it.hasNext()) {
1084: String str = ((String) it.next());
1085:
1086: if (isUriConstrained(uri, str)) {
1087: return;
1088: }
1089: }
1090: if (uri.length() == 0 && permitted.size() == 0) {
1091: return;
1092: }
1093: throw new CertPathValidatorException(
1094: "URI is not from a permitted subtree.");
1095: }
1096:
1097: private boolean isUriConstrained(String uri, String constraint) {
1098: String host = extractHostFromURL(uri);
1099: // a host
1100: if (!constraint.startsWith(".")) {
1101: if (host.equalsIgnoreCase(constraint)) {
1102: return true;
1103: }
1104: }
1105:
1106: // in sub domain or domain
1107: else if (withinDomain(host, constraint)) {
1108: return true;
1109: }
1110:
1111: return false;
1112: }
1113:
1114: private static String extractHostFromURL(String url) {
1115: // see RFC 1738
1116: // remove ':' after protocol, e.g. http:
1117: String sub = url.substring(url.indexOf(':') + 1);
1118: // extract host from Common Internet Scheme Syntax, e.g. http://
1119: if (sub.indexOf("//") != -1) {
1120: sub = sub.substring(sub.indexOf("//") + 2);
1121: }
1122: // first remove port, e.g. http://test.com:21
1123: if (sub.lastIndexOf(':') != -1) {
1124: sub = sub.substring(0, sub.lastIndexOf(':'));
1125: }
1126: // remove user and password, e.g. http://john:password@test.com
1127: sub = sub.substring(sub.indexOf(':') + 1);
1128: sub = sub.substring(sub.indexOf('@') + 1);
1129: // remove local parts, e.g. http://test.com/bla
1130: if (sub.indexOf('/') != -1) {
1131: sub = sub.substring(0, sub.indexOf('/'));
1132: }
1133: return sub;
1134: }
1135:
1136: /**
1137: * Checks if the given GeneralName is in the permitted set.
1138: *
1139: * @param name The GeneralName
1140: * @throws CertPathValidatorException If the <code>name</code>
1141: */
1142: public void checkPermitted(GeneralName name)
1143: throws CertPathValidatorException {
1144: switch (name.getTagNo()) {
1145: case 1:
1146: checkPermittedEmail(permittedSubtreesEmail,
1147: extractNameAsString(name));
1148: break;
1149: case 2:
1150: checkPermittedDNS(permittedSubtreesDNS, DERIA5String
1151: .getInstance(name.getName()).getString());
1152: break;
1153: case 4:
1154: checkPermittedDN(ASN1Sequence.getInstance(name.getName()
1155: .getDERObject()));
1156: break;
1157: case 6:
1158: checkPermittedURI(permittedSubtreesURI, DERIA5String
1159: .getInstance(name.getName()).getString());
1160: break;
1161: case 7:
1162: byte[] ip = ASN1OctetString.getInstance(name.getName())
1163: .getOctets();
1164:
1165: checkPermittedIP(permittedSubtreesIP, ip);
1166: }
1167: }
1168:
1169: /**
1170: * Check if the given GeneralName is contained in the excluded set.
1171: *
1172: * @param name The GeneralName.
1173: * @throws CertPathValidatorException If the <code>name</code> is
1174: * excluded.
1175: */
1176: public void checkExcluded(GeneralName name)
1177: throws CertPathValidatorException {
1178: switch (name.getTagNo()) {
1179: case 1:
1180: checkExcludedEmail(excludedSubtreesEmail,
1181: extractNameAsString(name));
1182: break;
1183: case 2:
1184: checkExcludedDNS(excludedSubtreesDNS, DERIA5String
1185: .getInstance(name.getName()).getString());
1186: break;
1187: case 4:
1188: checkExcludedDN(ASN1Sequence.getInstance(name.getName()
1189: .getDERObject()));
1190: break;
1191: case 6:
1192: checkExcludedURI(excludedSubtreesURI, DERIA5String
1193: .getInstance(name.getName()).getString());
1194: break;
1195: case 7:
1196: byte[] ip = ASN1OctetString.getInstance(name.getName())
1197: .getOctets();
1198:
1199: checkExcludedIP(excludedSubtreesIP, ip);
1200: }
1201: }
1202:
1203: /**
1204: * Updates the permitted set of these name constraints with the intersection
1205: * with the given subtree.
1206: *
1207: * @param subtree A subtree with an excluded GeneralName.
1208: */
1209:
1210: public void intersectPermittedSubtree(GeneralSubtree subtree) {
1211: GeneralName name = subtree.getBase();
1212: switch (name.getTagNo()) {
1213: case 1:
1214: permittedSubtreesEmail = intersectEmail(
1215: permittedSubtreesEmail, extractNameAsString(name));
1216: break;
1217: case 2:
1218: permittedSubtreesDNS = intersectDNS(permittedSubtreesDNS,
1219: DERIA5String.getInstance(name.getName())
1220: .getString());
1221: break;
1222: case 4:
1223: permittedSubtreesDN = intersectDN(permittedSubtreesDN,
1224: ASN1Sequence.getInstance(name.getName()
1225: .getDERObject()));
1226: break;
1227: case 6:
1228: permittedSubtreesURI = intersectURI(permittedSubtreesURI,
1229: DERIA5String.getInstance(name.getName())
1230: .getString());
1231: break;
1232: case 7:
1233: byte[] ip = ASN1OctetString.getInstance(name.getName())
1234: .getOctets();
1235:
1236: permittedSubtreesIP = intersectIP(permittedSubtreesIP, ip);
1237: }
1238: }
1239:
1240: private String extractNameAsString(GeneralName name) {
1241: return DERIA5String.getInstance(name.getName()).getString();
1242: }
1243:
1244: /**
1245: * Adds a subtree to the excluded set of these name constraints.
1246: *
1247: * @param subtree A subtree with an excluded GeneralName.
1248: */
1249: public void addExcludedSubtree(GeneralSubtree subtree) {
1250: GeneralName base = subtree.getBase();
1251:
1252: switch (base.getTagNo()) {
1253: case 1:
1254: excludedSubtreesEmail = unionEmail(excludedSubtreesEmail,
1255: DERIA5String.getInstance(base.getName())
1256: .getString());
1257: break;
1258: case 2:
1259: excludedSubtreesDNS = unionDNS(excludedSubtreesDNS,
1260: DERIA5String.getInstance(base.getName())
1261: .getString());
1262: break;
1263: case 4:
1264: excludedSubtreesDN = unionDN(excludedSubtreesDN,
1265: (ASN1Sequence) base.getName().getDERObject());
1266: break;
1267: case 6:
1268: excludedSubtreesURI = unionURI(excludedSubtreesURI,
1269: DERIA5String.getInstance(base.getName())
1270: .getString());
1271: break;
1272: case 7:
1273: excludedSubtreesIP = unionIP(excludedSubtreesIP,
1274: ASN1OctetString.getInstance(base.getName())
1275: .getOctets());
1276: break;
1277: }
1278: }
1279:
1280: /**
1281: * Returns the maximum IP address.
1282: *
1283: * @param ip1 The first IP address.
1284: * @param ip2 The second IP address.
1285: * @return The maximum IP address.
1286: */
1287: private static byte[] max(byte[] ip1, byte[] ip2) {
1288: for (int i = 0; i < ip1.length; i++) {
1289: if ((ip1[i] & 0xFFFF) > (ip2[i] & 0xFFFF)) {
1290: return ip1;
1291: }
1292: }
1293: return ip2;
1294: }
1295:
1296: /**
1297: * Returns the minimum IP address.
1298: *
1299: * @param ip1 The first IP address.
1300: * @param ip2 The second IP address.
1301: * @return The minimum IP address.
1302: */
1303: private static byte[] min(byte[] ip1, byte[] ip2) {
1304: for (int i = 0; i < ip1.length; i++) {
1305: if ((ip1[i] & 0xFFFF) < (ip2[i] & 0xFFFF)) {
1306: return ip1;
1307: }
1308: }
1309: return ip2;
1310: }
1311:
1312: /**
1313: * Compares IP address <code>ip1</code> with <code>ip2</code>. If ip1
1314: * is equal to ip2 0 is returned. If ip1 is bigger 1 is returned, -1
1315: * otherwise.
1316: *
1317: * @param ip1 The first IP address.
1318: * @param ip2 The second IP address.
1319: * @return 0 if ip1 is equal to ip2, 1 if ip1 is bigger, -1 otherwise.
1320: */
1321: private static int compareTo(byte[] ip1, byte[] ip2) {
1322: if (Arrays.areEqual(ip1, ip2)) {
1323: return 0;
1324: }
1325: if (Arrays.areEqual(max(ip1, ip2), ip1)) {
1326: return 1;
1327: }
1328: return -1;
1329: }
1330:
1331: /**
1332: * Returns the logical OR of the IP addresses <code>ip1</code> and
1333: * <code>ip2</code>.
1334: *
1335: * @param ip1 The first IP address.
1336: * @param ip2 The second IP address.
1337: *
1338: * @return The OR of <code>ip1</code> and <code>ip2</code>.
1339: */
1340: private static byte[] or(byte[] ip1, byte[] ip2) {
1341: byte[] temp = new byte[ip1.length];
1342: for (int i = 0; i < ip1.length; i++) {
1343: temp[i] = (byte) (ip1[i] | ip2[i]);
1344: }
1345: return temp;
1346: }
1347:
1348: public int hashCode() {
1349: return hashCollection(excludedSubtreesDN)
1350: + hashCollection(excludedSubtreesDNS)
1351: + hashCollection(excludedSubtreesEmail)
1352: + hashCollection(excludedSubtreesIP)
1353: + hashCollection(excludedSubtreesURI)
1354: + hashCollection(permittedSubtreesDN)
1355: + hashCollection(permittedSubtreesDNS)
1356: + hashCollection(permittedSubtreesEmail)
1357: + hashCollection(permittedSubtreesIP)
1358: + hashCollection(permittedSubtreesURI);
1359: }
1360:
1361: private int hashCollection(Collection coll) {
1362: if (coll == null) {
1363: return 0;
1364: }
1365: int hash = 0;
1366: Iterator it1 = coll.iterator();
1367: while (it1.hasNext()) {
1368: Object o = it1.next();
1369: if (o instanceof byte[]) {
1370: hash += Arrays.hashCode((byte[]) o);
1371: } else {
1372: hash += o.hashCode();
1373: }
1374: }
1375: return hash;
1376: }
1377:
1378: public boolean equals(Object o) {
1379: if (!(o instanceof PKIXNameConstraints)) {
1380: return false;
1381: }
1382: PKIXNameConstraints constraints = (PKIXNameConstraints) o;
1383: return collectionsAreEqual(constraints.excludedSubtreesDN,
1384: excludedSubtreesDN)
1385: && collectionsAreEqual(constraints.excludedSubtreesDNS,
1386: excludedSubtreesDNS)
1387: && collectionsAreEqual(
1388: constraints.excludedSubtreesEmail,
1389: excludedSubtreesEmail)
1390: && collectionsAreEqual(constraints.excludedSubtreesIP,
1391: excludedSubtreesIP)
1392: && collectionsAreEqual(constraints.excludedSubtreesURI,
1393: excludedSubtreesURI)
1394: && collectionsAreEqual(constraints.permittedSubtreesDN,
1395: permittedSubtreesDN)
1396: && collectionsAreEqual(
1397: constraints.permittedSubtreesDNS,
1398: permittedSubtreesDNS)
1399: && collectionsAreEqual(
1400: constraints.permittedSubtreesEmail,
1401: permittedSubtreesEmail)
1402: && collectionsAreEqual(constraints.permittedSubtreesIP,
1403: permittedSubtreesIP)
1404: && collectionsAreEqual(
1405: constraints.permittedSubtreesURI,
1406: permittedSubtreesURI);
1407: }
1408:
1409: private boolean collectionsAreEqual(Collection coll1,
1410: Collection coll2) {
1411: if (coll1 == coll2) {
1412: return true;
1413: }
1414: if (coll1 == null || coll2 == null) {
1415: return false;
1416: }
1417: if (coll1.size() != coll2.size()) {
1418: return false;
1419: }
1420: Iterator it1 = coll1.iterator();
1421:
1422: while (it1.hasNext()) {
1423: Object a = it1.next();
1424: Iterator it2 = coll2.iterator();
1425: boolean found = false;
1426: while (it2.hasNext()) {
1427: Object b = it2.next();
1428: if (equals(a, b)) {
1429: found = true;
1430: break;
1431: }
1432: }
1433: if (!found) {
1434: return false;
1435: }
1436: }
1437: return true;
1438: }
1439:
1440: private boolean equals(Object o1, Object o2) {
1441: if (o1 == o2) {
1442: return true;
1443: }
1444: if (o1 == null || o2 == null) {
1445: return false;
1446: }
1447: if (o1 instanceof byte[] && o2 instanceof byte[]) {
1448: return Arrays.areEqual((byte[]) o1, (byte[]) o2);
1449: } else {
1450: return o1.equals(o2);
1451: }
1452: }
1453:
1454: /**
1455: * Stringifies an IPv4 or v6 address with subnet mask.
1456: *
1457: * @param ip The IP with subnet mask.
1458: * @return The stringified IP address.
1459: */
1460: private String stringifyIP(byte[] ip) {
1461: String temp = "";
1462: for (int i = 0; i < ip.length / 2; i++) {
1463: temp += Integer.toString(ip[i] & 0x00FF) + ".";
1464: }
1465: temp = temp.substring(0, temp.length() - 1);
1466: temp += "/";
1467: for (int i = ip.length / 2; i < ip.length; i++) {
1468: temp += Integer.toString(ip[i] & 0x00FF) + ".";
1469: }
1470: temp = temp.substring(0, temp.length() - 1);
1471: return temp;
1472: }
1473:
1474: private String stringifyIPCollection(Set ips) {
1475: String temp = "";
1476: temp += "[";
1477: for (Iterator it = ips.iterator(); it.hasNext();) {
1478: temp += stringifyIP((byte[]) it.next()) + ",";
1479: }
1480: if (temp.length() > 1) {
1481: temp = temp.substring(0, temp.length() - 1);
1482: }
1483: temp += "]";
1484: return temp;
1485: }
1486:
1487: public String toString() {
1488: String temp = "";
1489: temp += "permitted:\n";
1490: if (permittedSubtreesDN != null) {
1491: temp += "DN:\n";
1492: temp += permittedSubtreesDN.toString() + "\n";
1493: }
1494: if (permittedSubtreesDNS != null) {
1495: temp += "DNS:\n";
1496: temp += permittedSubtreesDNS.toString() + "\n";
1497: }
1498: if (permittedSubtreesEmail != null) {
1499: temp += "Email:\n";
1500: temp += permittedSubtreesEmail.toString() + "\n";
1501: }
1502: if (permittedSubtreesURI != null) {
1503: temp += "URI:\n";
1504: temp += permittedSubtreesURI.toString() + "\n";
1505: }
1506: if (permittedSubtreesIP != null) {
1507: temp += "IP:\n";
1508: temp += stringifyIPCollection(permittedSubtreesIP) + "\n";
1509: }
1510: temp += "excluded:\n";
1511: if (!excludedSubtreesDN.isEmpty()) {
1512: temp += "DN:\n";
1513: temp += excludedSubtreesDN.toString() + "\n";
1514: }
1515: if (!excludedSubtreesDNS.isEmpty()) {
1516: temp += "DNS:\n";
1517: temp += excludedSubtreesDNS.toString() + "\n";
1518: }
1519: if (!excludedSubtreesEmail.isEmpty()) {
1520: temp += "Email:\n";
1521: temp += excludedSubtreesEmail.toString() + "\n";
1522: }
1523: if (!excludedSubtreesURI.isEmpty()) {
1524: temp += "URI:\n";
1525: temp += excludedSubtreesURI.toString() + "\n";
1526: }
1527: if (!excludedSubtreesIP.isEmpty()) {
1528: temp += "IP:\n";
1529: temp += stringifyIPCollection(excludedSubtreesIP) + "\n";
1530: }
1531: return temp;
1532: }
1533: }
|