001 /**
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one or more
004 * contributor license agreements. See the NOTICE file distributed with
005 * this work for additional information regarding copyright ownership.
006 * The ASF licenses this file to You under the Apache License, Version 2.0
007 * (the "License"); you may not use this file except in compliance with
008 * the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package org.apache.geronimo.util.asn1.x509;
020
021 import java.util.Enumeration;
022 import java.util.Hashtable;
023 import java.util.Vector;
024
025 import org.apache.geronimo.util.asn1.ASN1Encodable;
026 import org.apache.geronimo.util.asn1.ASN1EncodableVector;
027 import org.apache.geronimo.util.asn1.ASN1OctetString;
028 import org.apache.geronimo.util.asn1.ASN1Sequence;
029 import org.apache.geronimo.util.asn1.ASN1TaggedObject;
030 import org.apache.geronimo.util.asn1.DERBoolean;
031 import org.apache.geronimo.util.asn1.DERObject;
032 import org.apache.geronimo.util.asn1.DERObjectIdentifier;
033 import org.apache.geronimo.util.asn1.DERSequence;
034
035 public class X509Extensions
036 extends ASN1Encodable
037 {
038 /**
039 * Subject Directory Attributes
040 */
041 public static final DERObjectIdentifier SubjectDirectoryAttributes = new DERObjectIdentifier("2.5.29.9");
042
043 /**
044 * Subject Key Identifier
045 */
046 public static final DERObjectIdentifier SubjectKeyIdentifier = new DERObjectIdentifier("2.5.29.14");
047
048 /**
049 * Key Usage
050 */
051 public static final DERObjectIdentifier KeyUsage = new DERObjectIdentifier("2.5.29.15");
052
053 /**
054 * Private Key Usage Period
055 */
056 public static final DERObjectIdentifier PrivateKeyUsagePeriod = new DERObjectIdentifier("2.5.29.16");
057
058 /**
059 * Subject Alternative Name
060 */
061 public static final DERObjectIdentifier SubjectAlternativeName = new DERObjectIdentifier("2.5.29.17");
062
063 /**
064 * Issuer Alternative Name
065 */
066 public static final DERObjectIdentifier IssuerAlternativeName = new DERObjectIdentifier("2.5.29.18");
067
068 /**
069 * Basic Constraints
070 */
071 public static final DERObjectIdentifier BasicConstraints = new DERObjectIdentifier("2.5.29.19");
072
073 /**
074 * CRL Number
075 */
076 public static final DERObjectIdentifier CRLNumber = new DERObjectIdentifier("2.5.29.20");
077
078 /**
079 * Reason code
080 */
081 public static final DERObjectIdentifier ReasonCode = new DERObjectIdentifier("2.5.29.21");
082
083 /**
084 * Hold Instruction Code
085 */
086 public static final DERObjectIdentifier InstructionCode = new DERObjectIdentifier("2.5.29.23");
087
088 /**
089 * Invalidity Date
090 */
091 public static final DERObjectIdentifier InvalidityDate = new DERObjectIdentifier("2.5.29.24");
092
093 /**
094 * Delta CRL indicator
095 */
096 public static final DERObjectIdentifier DeltaCRLIndicator = new DERObjectIdentifier("2.5.29.27");
097
098 /**
099 * Issuing Distribution Point
100 */
101 public static final DERObjectIdentifier IssuingDistributionPoint = new DERObjectIdentifier("2.5.29.28");
102
103 /**
104 * Certificate Issuer
105 */
106 public static final DERObjectIdentifier CertificateIssuer = new DERObjectIdentifier("2.5.29.29");
107
108 /**
109 * Name Constraints
110 */
111 public static final DERObjectIdentifier NameConstraints = new DERObjectIdentifier("2.5.29.30");
112
113 /**
114 * CRL Distribution Points
115 */
116 public static final DERObjectIdentifier CRLDistributionPoints = new DERObjectIdentifier("2.5.29.31");
117
118 /**
119 * Certificate Policies
120 */
121 public static final DERObjectIdentifier CertificatePolicies = new DERObjectIdentifier("2.5.29.32");
122
123 /**
124 * Policy Mappings
125 */
126 public static final DERObjectIdentifier PolicyMappings = new DERObjectIdentifier("2.5.29.33");
127
128 /**
129 * Authority Key Identifier
130 */
131 public static final DERObjectIdentifier AuthorityKeyIdentifier = new DERObjectIdentifier("2.5.29.35");
132
133 /**
134 * Policy Constraints
135 */
136 public static final DERObjectIdentifier PolicyConstraints = new DERObjectIdentifier("2.5.29.36");
137
138 /**
139 * Extended Key Usage
140 */
141 public static final DERObjectIdentifier ExtendedKeyUsage = new DERObjectIdentifier("2.5.29.37");
142
143 /**
144 * Freshest CRL
145 */
146 public static final DERObjectIdentifier FreshestCRL = new DERObjectIdentifier("2.5.29.46");
147
148 /**
149 * Inhibit Any Policy
150 */
151 public static final DERObjectIdentifier InhibitAnyPolicy = new DERObjectIdentifier("2.5.29.54");
152
153 /**
154 * Authority Info Access
155 */
156 public static final DERObjectIdentifier AuthorityInfoAccess= new DERObjectIdentifier("1.3.6.1.5.5.7.1.1");
157
158 /**
159 * Subject Info Access
160 */
161 public static final DERObjectIdentifier SubjectInfoAccess= new DERObjectIdentifier("1.3.6.1.5.5.7.1.11");
162
163 private Hashtable extensions = new Hashtable();
164 private Vector ordering = new Vector();
165
166 public static X509Extensions getInstance(
167 ASN1TaggedObject obj,
168 boolean explicit)
169 {
170 return getInstance(ASN1Sequence.getInstance(obj, explicit));
171 }
172
173 public static X509Extensions getInstance(
174 Object obj)
175 {
176 if (obj == null || obj instanceof X509Extensions)
177 {
178 return (X509Extensions)obj;
179 }
180
181 if (obj instanceof ASN1Sequence)
182 {
183 return new X509Extensions((ASN1Sequence)obj);
184 }
185
186 if (obj instanceof ASN1TaggedObject)
187 {
188 return getInstance(((ASN1TaggedObject)obj).getObject());
189 }
190
191 throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
192 }
193
194 /**
195 * Constructor from ASN1Sequence.
196 *
197 * the extensions are a list of constructed sequences, either with (OID, OctetString) or (OID, Boolean, OctetString)
198 */
199 public X509Extensions(
200 ASN1Sequence seq)
201 {
202 Enumeration e = seq.getObjects();
203
204 while (e.hasMoreElements())
205 {
206 ASN1Sequence s = (ASN1Sequence)e.nextElement();
207
208 if (s.size() == 3)
209 {
210 extensions.put(s.getObjectAt(0), new X509Extension((DERBoolean)s.getObjectAt(1), (ASN1OctetString)s.getObjectAt(2)));
211 }
212 else
213 {
214 extensions.put(s.getObjectAt(0), new X509Extension(false, (ASN1OctetString)s.getObjectAt(1)));
215 }
216
217 ordering.addElement(s.getObjectAt(0));
218 }
219 }
220
221 /**
222 * constructor from a table of extensions.
223 * <p>
224 * it's is assumed the table contains OID/String pairs.
225 */
226 public X509Extensions(
227 Hashtable extensions)
228 {
229 this(null, extensions);
230 }
231
232 /**
233 * Constructor from a table of extensions with ordering.
234 * <p>
235 * It's is assumed the table contains OID/String pairs.
236 */
237 public X509Extensions(
238 Vector ordering,
239 Hashtable extensions)
240 {
241 Enumeration e;
242
243 if (ordering == null)
244 {
245 e = extensions.keys();
246 }
247 else
248 {
249 e = ordering.elements();
250 }
251
252 while (e.hasMoreElements())
253 {
254 this.ordering.addElement(e.nextElement());
255 }
256
257 e = this.ordering.elements();
258
259 while (e.hasMoreElements())
260 {
261 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
262 X509Extension ext = (X509Extension)extensions.get(oid);
263
264 this.extensions.put(oid, ext);
265 }
266 }
267
268 /**
269 * Constructor from two vectors
270 *
271 * @param objectIDs a vector of the object identifiers.
272 * @param values a vector of the extension values.
273 */
274 public X509Extensions(
275 Vector objectIDs,
276 Vector values)
277 {
278 Enumeration e = objectIDs.elements();
279
280 while (e.hasMoreElements())
281 {
282 this.ordering.addElement(e.nextElement());
283 }
284
285 int count = 0;
286
287 e = this.ordering.elements();
288
289 while (e.hasMoreElements())
290 {
291 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
292 X509Extension ext = (X509Extension)values.elementAt(count);
293
294 this.extensions.put(oid, ext);
295 count++;
296 }
297 }
298
299 /**
300 * return an Enumeration of the extension field's object ids.
301 */
302 public Enumeration oids()
303 {
304 return ordering.elements();
305 }
306
307 /**
308 * return the extension represented by the object identifier
309 * passed in.
310 *
311 * @return the extension if it's present, null otherwise.
312 */
313 public X509Extension getExtension(
314 DERObjectIdentifier oid)
315 {
316 return (X509Extension)extensions.get(oid);
317 }
318
319 /**
320 * <pre>
321 * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
322 *
323 * Extension ::= SEQUENCE {
324 * extnId EXTENSION.&id ({ExtensionSet}),
325 * critical BOOLEAN DEFAULT FALSE,
326 * extnValue OCTET STRING }
327 * </pre>
328 */
329 public DERObject toASN1Object()
330 {
331 ASN1EncodableVector vec = new ASN1EncodableVector();
332 Enumeration e = ordering.elements();
333
334 while (e.hasMoreElements())
335 {
336 DERObjectIdentifier oid = (DERObjectIdentifier)e.nextElement();
337 X509Extension ext = (X509Extension)extensions.get(oid);
338 ASN1EncodableVector v = new ASN1EncodableVector();
339
340 v.add(oid);
341
342 if (ext.isCritical())
343 {
344 v.add(new DERBoolean(true));
345 }
346
347 v.add(ext.getValue());
348
349 vec.add(new DERSequence(v));
350 }
351
352 return new DERSequence(vec);
353 }
354
355 public int hashCode()
356 {
357 Enumeration e = extensions.keys();
358 int hashCode = 0;
359
360 while (e.hasMoreElements())
361 {
362 Object o = e.nextElement();
363
364 hashCode ^= o.hashCode();
365 hashCode ^= extensions.get(o).hashCode();
366 }
367
368 return hashCode;
369 }
370
371 public boolean equals(
372 Object o)
373 {
374 if (o == null || !(o instanceof X509Extensions))
375 {
376 return false;
377 }
378
379 X509Extensions other = (X509Extensions)o;
380
381 Enumeration e1 = extensions.keys();
382 Enumeration e2 = other.extensions.keys();
383
384 while (e1.hasMoreElements() && e2.hasMoreElements())
385 {
386 Object o1 = e1.nextElement();
387 Object o2 = e2.nextElement();
388
389 if (!o1.equals(o2))
390 {
391 return false;
392 }
393 }
394
395 if (e1.hasMoreElements() || e2.hasMoreElements())
396 {
397 return false;
398 }
399
400 return true;
401 }
402 }