001package org.apache.commons.ssl.org.bouncycastle.asn1.x509; 002 003import java.math.BigInteger; 004 005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object; 008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject; 011import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence; 012import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject; 013 014/** 015 * Class for containing a restriction object subtrees in NameConstraints. See 016 * RFC 3280. 017 * 018 * <pre> 019 * 020 * GeneralSubtree ::= SEQUENCE 021 * { 022 * base GeneralName, 023 * minimum [0] BaseDistance DEFAULT 0, 024 * maximum [1] BaseDistance OPTIONAL 025 * } 026 * </pre> 027 * 028 * @see org.bouncycastle.asn1.x509.NameConstraints 029 * 030 */ 031public class GeneralSubtree 032 extends ASN1Object 033{ 034 private static final BigInteger ZERO = BigInteger.valueOf(0); 035 036 private GeneralName base; 037 038 private ASN1Integer minimum; 039 040 private ASN1Integer maximum; 041 042 private GeneralSubtree( 043 ASN1Sequence seq) 044 { 045 base = GeneralName.getInstance(seq.getObjectAt(0)); 046 047 switch (seq.size()) 048 { 049 case 1: 050 break; 051 case 2: 052 ASN1TaggedObject o = ASN1TaggedObject.getInstance(seq.getObjectAt(1)); 053 switch (o.getTagNo()) 054 { 055 case 0: 056 minimum = ASN1Integer.getInstance(o, false); 057 break; 058 case 1: 059 maximum = ASN1Integer.getInstance(o, false); 060 break; 061 default: 062 throw new IllegalArgumentException("Bad tag number: " 063 + o.getTagNo()); 064 } 065 break; 066 case 3: 067 { 068 { 069 ASN1TaggedObject oMin = ASN1TaggedObject.getInstance(seq.getObjectAt(1)); 070 if (oMin.getTagNo() != 0) 071 { 072 throw new IllegalArgumentException("Bad tag number for 'minimum': " + oMin.getTagNo()); 073 } 074 minimum = ASN1Integer.getInstance(oMin, false); 075 } 076 077 { 078 ASN1TaggedObject oMax = ASN1TaggedObject.getInstance(seq.getObjectAt(2)); 079 if (oMax.getTagNo() != 1) 080 { 081 throw new IllegalArgumentException("Bad tag number for 'maximum': " + oMax.getTagNo()); 082 } 083 maximum = ASN1Integer.getInstance(oMax, false); 084 } 085 086 break; 087 } 088 default: 089 throw new IllegalArgumentException("Bad sequence size: " 090 + seq.size()); 091 } 092 } 093 094 /** 095 * Constructor from a given details. 096 * 097 * According RFC 3280, the minimum and maximum fields are not used with any 098 * name forms, thus minimum MUST be zero, and maximum MUST be absent. 099 * <p> 100 * If minimum is <code>null</code>, zero is assumed, if 101 * maximum is <code>null</code>, maximum is absent. 102 * 103 * @param base 104 * A restriction. 105 * @param minimum 106 * Minimum 107 * 108 * @param maximum 109 * Maximum 110 */ 111 public GeneralSubtree( 112 GeneralName base, 113 BigInteger minimum, 114 BigInteger maximum) 115 { 116 this.base = base; 117 if (maximum != null) 118 { 119 this.maximum = new ASN1Integer(maximum); 120 } 121 if (minimum == null) 122 { 123 this.minimum = null; 124 } 125 else 126 { 127 this.minimum = new ASN1Integer(minimum); 128 } 129 } 130 131 public GeneralSubtree(GeneralName base) 132 { 133 this(base, null, null); 134 } 135 136 public static GeneralSubtree getInstance( 137 ASN1TaggedObject o, 138 boolean explicit) 139 { 140 return new GeneralSubtree(ASN1Sequence.getInstance(o, explicit)); 141 } 142 143 public static GeneralSubtree getInstance( 144 Object obj) 145 { 146 if (obj == null) 147 { 148 return null; 149 } 150 151 if (obj instanceof GeneralSubtree) 152 { 153 return (GeneralSubtree) obj; 154 } 155 156 return new GeneralSubtree(ASN1Sequence.getInstance(obj)); 157 } 158 159 public GeneralName getBase() 160 { 161 return base; 162 } 163 164 public BigInteger getMinimum() 165 { 166 if (minimum == null) 167 { 168 return ZERO; 169 } 170 171 return minimum.getValue(); 172 } 173 174 public BigInteger getMaximum() 175 { 176 if (maximum == null) 177 { 178 return null; 179 } 180 181 return maximum.getValue(); 182 } 183 184 /** 185 * Produce an object suitable for an ASN1OutputStream. 186 * 187 * Returns: 188 * 189 * <pre> 190 * GeneralSubtree ::= SEQUENCE 191 * { 192 * base GeneralName, 193 * minimum [0] BaseDistance DEFAULT 0, 194 * maximum [1] BaseDistance OPTIONAL 195 * } 196 * </pre> 197 * 198 * @return a ASN1Primitive 199 */ 200 public ASN1Primitive toASN1Primitive() 201 { 202 ASN1EncodableVector v = new ASN1EncodableVector(); 203 204 v.add(base); 205 206 if (minimum != null && !minimum.getValue().equals(ZERO)) 207 { 208 v.add(new DERTaggedObject(false, 0, minimum)); 209 } 210 211 if (maximum != null) 212 { 213 v.add(new DERTaggedObject(false, 1, maximum)); 214 } 215 216 return new DERSequence(v); 217 } 218}