Path: blob/master/src/java.base/share/classes/sun/security/x509/CRLExtensions.java
41159 views
/*1* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.x509;2627import java.io.IOException;28import java.io.OutputStream;29import java.lang.reflect.Constructor;30import java.lang.reflect.InvocationTargetException;31import java.security.cert.CRLException;32import java.security.cert.CertificateException;33import java.util.Collection;34import java.util.Collections;35import java.util.Enumeration;36import java.util.Map;37import java.util.TreeMap;3839import sun.security.util.*;4041/**42* This class defines the CRL Extensions.43* It is used for both CRL Extensions and CRL Entry Extensions,44* which are defined are follows:45* <pre>46* TBSCertList ::= SEQUENCE {47* version Version OPTIONAL, -- if present, must be v248* signature AlgorithmIdentifier,49* issuer Name,50* thisUpdate Time,51* nextUpdate Time OPTIONAL,52* revokedCertificates SEQUENCE OF SEQUENCE {53* userCertificate CertificateSerialNumber,54* revocationDate Time,55* crlEntryExtensions Extensions OPTIONAL -- if present, must be v256* } OPTIONAL,57* crlExtensions [0] EXPLICIT Extensions OPTIONAL -- if present, must be v258* }59* </pre>60*61* @author Hemma Prafullchandra62*/63public class CRLExtensions {6465private Map<String,Extension> map = Collections.synchronizedMap(66new TreeMap<String,Extension>());67private boolean unsupportedCritExt = false;6869/**70* Default constructor.71*/72public CRLExtensions() { }7374/**75* Create the object, decoding the values from the passed DER stream.76*77* @param in the DerInputStream to read the Extension from, i.e. the78* sequence of extensions.79* @exception CRLException on decoding errors.80*/81public CRLExtensions(DerInputStream in) throws CRLException {82init(in);83}8485// helper routine86private void init(DerInputStream derStrm) throws CRLException {87try {88DerInputStream str = derStrm;8990byte nextByte = (byte)derStrm.peekByte();91// check for context specific byte 0; skip it92if (((nextByte & 0x0c0) == 0x080) &&93((nextByte & 0x01f) == 0x000)) {94DerValue val = str.getDerValue();95str = val.data;96}9798DerValue[] exts = str.getSequence(5);99for (int i = 0; i < exts.length; i++) {100Extension ext = new Extension(exts[i]);101parseExtension(ext);102}103} catch (IOException e) {104throw new CRLException("Parsing error: " + e.toString());105}106}107108private static final Class<?>[] PARAMS = {Boolean.class, Object.class};109110// Parse the encoded extension111private void parseExtension(Extension ext) throws CRLException {112try {113Class<?> extClass = OIDMap.getClass(ext.getExtensionId());114if (extClass == null) { // Unsupported extension115if (ext.isCritical())116unsupportedCritExt = true;117if (map.put(ext.getExtensionId().toString(), ext) != null)118throw new CRLException("Duplicate extensions not allowed");119return;120}121Constructor<?> cons = extClass.getConstructor(PARAMS);122Object[] passed = new Object[] {Boolean.valueOf(ext.isCritical()),123ext.getExtensionValue()};124CertAttrSet<?> crlExt = (CertAttrSet<?>)cons.newInstance(passed);125if (map.put(crlExt.getName(), (Extension)crlExt) != null) {126throw new CRLException("Duplicate extensions not allowed");127}128} catch (InvocationTargetException invk) {129throw new CRLException(invk.getCause().getMessage());130} catch (Exception e) {131throw new CRLException(e.toString());132}133}134135/**136* Encode the extensions in DER form to the stream.137*138* @param out the DerOutputStream to marshal the contents to.139* @param isExplicit the tag indicating whether this is an entry140* extension (false) or a CRL extension (true).141* @exception CRLException on encoding errors.142*/143public void encode(OutputStream out, boolean isExplicit)144throws CRLException {145try {146DerOutputStream extOut = new DerOutputStream();147Collection<Extension> allExts = map.values();148Object[] objs = allExts.toArray();149150for (int i = 0; i < objs.length; i++) {151if (objs[i] instanceof CertAttrSet)152((CertAttrSet)objs[i]).encode(extOut);153else if (objs[i] instanceof Extension)154((Extension)objs[i]).encode(extOut);155else156throw new CRLException("Illegal extension object");157}158159DerOutputStream seq = new DerOutputStream();160seq.write(DerValue.tag_Sequence, extOut);161162DerOutputStream tmp = new DerOutputStream();163if (isExplicit)164tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,165true, (byte)0), seq);166else167tmp = seq;168169out.write(tmp.toByteArray());170} catch (IOException e) {171throw new CRLException("Encoding error: " + e.toString());172} catch (CertificateException e) {173throw new CRLException("Encoding error: " + e.toString());174}175}176177/**178* Get the extension with this alias.179*180* @param alias the identifier string for the extension to retrieve.181*/182public Extension get(String alias) {183X509AttributeName attr = new X509AttributeName(alias);184String name;185String id = attr.getPrefix();186if (id.equalsIgnoreCase(X509CertImpl.NAME)) { // fully qualified187int index = alias.lastIndexOf('.');188name = alias.substring(index + 1);189} else190name = alias;191return map.get(name);192}193194/**195* Set the extension value with this alias.196*197* @param alias the identifier string for the extension to set.198* @param obj the Object to set the extension identified by the199* alias.200*/201public void set(String alias, Object obj) {202map.put(alias, (Extension)obj);203}204205/**206* Delete the extension value with this alias.207*208* @param alias the identifier string for the extension to delete.209*/210public void delete(String alias) {211map.remove(alias);212}213214/**215* Return an enumeration of the extensions.216* @return an enumeration of the extensions in this CRL.217*/218public Enumeration<Extension> getElements() {219return Collections.enumeration(map.values());220}221222/**223* Return a collection view of the extensions.224* @return a collection view of the extensions in this CRL.225*/226public Collection<Extension> getAllExtensions() {227return map.values();228}229230/**231* Return true if a critical extension is found that is232* not supported, otherwise return false.233*/234public boolean hasUnsupportedCriticalExtension() {235return unsupportedCritExt;236}237238/**239* Compares this CRLExtensions for equality with the specified240* object. If the {@code other} object is an241* {@code instanceof} {@code CRLExtensions}, then242* all the entries are compared with the entries from this.243*244* @param other the object to test for equality with this CRLExtensions.245* @return true iff all the entries match that of the Other,246* false otherwise.247*/248public boolean equals(Object other) {249if (this == other)250return true;251if (!(other instanceof CRLExtensions))252return false;253Collection<Extension> otherC =254((CRLExtensions)other).getAllExtensions();255Object[] objs = otherC.toArray();256257int len = objs.length;258if (len != map.size())259return false;260261Extension otherExt, thisExt;262String key = null;263for (int i = 0; i < len; i++) {264if (objs[i] instanceof CertAttrSet)265key = ((CertAttrSet)objs[i]).getName();266otherExt = (Extension)objs[i];267if (key == null)268key = otherExt.getExtensionId().toString();269thisExt = map.get(key);270if (thisExt == null)271return false;272if (! thisExt.equals(otherExt))273return false;274}275return true;276}277278/**279* Returns a hashcode value for this CRLExtensions.280*281* @return the hashcode value.282*/283public int hashCode() {284return map.hashCode();285}286287/**288* Returns a string representation of this {@code CRLExtensions} object289* in the form of a set of entries, enclosed in braces and separated290* by the ASCII characters "<code>, </code>" (comma and space).291* <p>Overrides to {@code toString} method of {@code Object}.292*293* @return a string representation of this CRLExtensions.294*/295public String toString() {296return map.toString();297}298}299300301