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