1 /* 2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.security.x509; 26 27 import java.io.IOException; 28 import java.io.OutputStream; 29 import java.util.Enumeration; 30 31 import sun.security.util.DerValue; 32 import sun.security.util.DerOutputStream; 33 34 /** 35 * Represents the CRL Certificate Issuer Extension (OID = 2.5.29.29). 36 * <p> 37 * The CRL certificate issuer extension identifies the certificate issuer 38 * associated with an entry in an indirect CRL, i.e. a CRL that has the 39 * indirectCRL indicator set in its issuing distribution point extension. If 40 * this extension is not present on the first entry in an indirect CRL, the 41 * certificate issuer defaults to the CRL issuer. On subsequent entries 42 * in an indirect CRL, if this extension is not present, the certificate 43 * issuer for the entry is the same as that for the preceding entry. 44 * <p> 45 * If used by conforming CRL issuers, this extension is always 46 * critical. If an implementation ignored this extension it could not 47 * correctly attribute CRL entries to certificates. PKIX (RFC 3280) 48 * RECOMMENDS that implementations recognize this extension. 49 * <p> 50 * The ASN.1 definition for this is: 51 * <pre> 52 * id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 } 53 * 54 * certificateIssuer ::= GeneralNames 55 * </pre> 56 * 57 * @author Anne Anderson 58 * @author Sean Mullan 59 * @since 1.5 60 * @see Extension 61 * @see CertAttrSet 62 */ 63 public class CertificateIssuerExtension extends Extension 64 implements CertAttrSet<String> { 65 66 /** 67 * Attribute names. 68 */ 69 public static final String NAME = "CertificateIssuer"; 70 public static final String ISSUER = "issuer"; 71 72 private GeneralNames names; 73 74 /** 75 * Encode this extension 76 */ encodeThis()77 private void encodeThis() throws IOException { 78 if (names == null || names.isEmpty()) { 79 this.extensionValue = null; 80 return; 81 } 82 DerOutputStream os = new DerOutputStream(); 83 names.encode(os); 84 this.extensionValue = os.toByteArray(); 85 } 86 87 /** 88 * Create a CertificateIssuerExtension containing the specified issuer name. 89 * Criticality is automatically set to true. 90 * 91 * @param issuer the certificate issuer 92 * @throws IOException on error 93 */ CertificateIssuerExtension(GeneralNames issuer)94 public CertificateIssuerExtension(GeneralNames issuer) throws IOException { 95 this.extensionId = PKIXExtensions.CertificateIssuer_Id; 96 this.critical = true; 97 this.names = issuer; 98 encodeThis(); 99 } 100 101 /** 102 * Create a CertificateIssuerExtension from the specified DER encoded 103 * value of the same. 104 * 105 * @param critical true if the extension is to be treated as critical. 106 * @param value an array of DER encoded bytes of the actual value 107 * @throws ClassCastException if value is not an array of bytes 108 * @throws IOException on error 109 */ CertificateIssuerExtension(Boolean critical, Object value)110 public CertificateIssuerExtension(Boolean critical, Object value) 111 throws IOException { 112 this.extensionId = PKIXExtensions.CertificateIssuer_Id; 113 this.critical = critical.booleanValue(); 114 115 this.extensionValue = (byte[]) value; 116 DerValue val = new DerValue(this.extensionValue); 117 this.names = new GeneralNames(val); 118 } 119 120 /** 121 * Set the attribute value. 122 * 123 * @throws IOException on error 124 */ set(String name, Object obj)125 public void set(String name, Object obj) throws IOException { 126 if (name.equalsIgnoreCase(ISSUER)) { 127 if (!(obj instanceof GeneralNames)) { 128 throw new IOException("Attribute value must be of type " + 129 "GeneralNames"); 130 } 131 this.names = (GeneralNames)obj; 132 } else { 133 throw new IOException("Attribute name not recognized by " + 134 "CertAttrSet:CertificateIssuer"); 135 } 136 encodeThis(); 137 } 138 139 /** 140 * Gets the attribute value. 141 * 142 * @throws IOException on error 143 */ get(String name)144 public GeneralNames get(String name) throws IOException { 145 if (name.equalsIgnoreCase(ISSUER)) { 146 return names; 147 } else { 148 throw new IOException("Attribute name not recognized by " + 149 "CertAttrSet:CertificateIssuer"); 150 } 151 } 152 153 /** 154 * Deletes the attribute value. 155 * 156 * @throws IOException on error 157 */ delete(String name)158 public void delete(String name) throws IOException { 159 if (name.equalsIgnoreCase(ISSUER)) { 160 names = null; 161 } else { 162 throw new IOException("Attribute name not recognized by " + 163 "CertAttrSet:CertificateIssuer"); 164 } 165 encodeThis(); 166 } 167 168 /** 169 * Returns a printable representation of the certificate issuer. 170 */ toString()171 public String toString() { 172 return super.toString() + "Certificate Issuer [\n" + 173 String.valueOf(names) + "]\n"; 174 } 175 176 /** 177 * Write the extension to the OutputStream. 178 * 179 * @param out the OutputStream to write the extension to 180 * @exception IOException on encoding errors 181 */ encode(OutputStream out)182 public void encode(OutputStream out) throws IOException { 183 DerOutputStream tmp = new DerOutputStream(); 184 if (extensionValue == null) { 185 extensionId = PKIXExtensions.CertificateIssuer_Id; 186 critical = true; 187 encodeThis(); 188 } 189 super.encode(tmp); 190 out.write(tmp.toByteArray()); 191 } 192 193 /** 194 * Return an enumeration of names of attributes existing within this 195 * attribute. 196 */ getElements()197 public Enumeration<String> getElements() { 198 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 199 elements.addElement(ISSUER); 200 return elements.elements(); 201 } 202 203 /** 204 * Return the name of this attribute. 205 */ getName()206 public String getName() { 207 return NAME; 208 } 209 } 210