1 /* 2 * Copyright (c) 2004, 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 26 package sun.security.x509; 27 28 import java.io.IOException; 29 import java.io.OutputStream; 30 31 import java.util.*; 32 33 import sun.security.util.DerOutputStream; 34 import sun.security.util.DerValue; 35 36 /** 37 * The Authority Information Access Extension (OID = 1.3.6.1.5.5.7.1.1). 38 * <p> 39 * The AIA extension identifies how to access CA information and services 40 * for the certificate in which it appears. It enables CAs to issue their 41 * certificates pre-configured with the URLs appropriate for contacting 42 * services relevant to those certificates. For example, a CA may issue a 43 * certificate that identifies the specific OCSP Responder to use when 44 * performing on-line validation of that certificate. 45 * <p> 46 * This extension is defined in <a href="http://www.ietf.org/rfc/rfc3280.txt"> 47 * Internet X.509 PKI Certificate and Certificate Revocation List 48 * (CRL) Profile</a>. The profile permits 49 * the extension to be included in end-entity or CA certificates, 50 * and it must be marked as non-critical. Its ASN.1 definition is as follows: 51 * <pre> 52 * id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } 53 * 54 * AuthorityInfoAccessSyntax ::= 55 * SEQUENCE SIZE (1..MAX) OF AccessDescription 56 * 57 * AccessDescription ::= SEQUENCE { 58 * accessMethod OBJECT IDENTIFIER, 59 * accessLocation GeneralName } 60 * </pre> 61 * <p> 62 * @see Extension 63 * @see CertAttrSet 64 */ 65 66 public class AuthorityInfoAccessExtension extends Extension 67 implements CertAttrSet<String> { 68 69 /** 70 * Identifier for this attribute, to be used with the 71 * get, set, delete methods of Certificate, x509 type. 72 */ 73 public static final String IDENT = 74 "x509.info.extensions.AuthorityInfoAccess"; 75 76 /** 77 * Attribute name. 78 */ 79 public static final String NAME = "AuthorityInfoAccess"; 80 public static final String DESCRIPTIONS = "descriptions"; 81 82 /** 83 * The List of AccessDescription objects. 84 */ 85 private List<AccessDescription> accessDescriptions; 86 87 /** 88 * Create an AuthorityInfoAccessExtension from a List of 89 * AccessDescription; the criticality is set to false. 90 * 91 * @param accessDescriptions the List of AccessDescription 92 * @throws IOException on error 93 */ AuthorityInfoAccessExtension( List<AccessDescription> accessDescriptions)94 public AuthorityInfoAccessExtension( 95 List<AccessDescription> accessDescriptions) throws IOException { 96 this.extensionId = PKIXExtensions.AuthInfoAccess_Id; 97 this.critical = false; 98 this.accessDescriptions = accessDescriptions; 99 encodeThis(); 100 } 101 102 /** 103 * Create the extension from the passed DER encoded value of the same. 104 * 105 * @param critical true if the extension is to be treated as critical. 106 * @param value Array of DER encoded bytes of the actual value. 107 * @exception IOException on error. 108 */ AuthorityInfoAccessExtension(Boolean critical, Object value)109 public AuthorityInfoAccessExtension(Boolean critical, Object value) 110 throws IOException { 111 this.extensionId = PKIXExtensions.AuthInfoAccess_Id; 112 this.critical = critical.booleanValue(); 113 114 if (!(value instanceof byte[])) { 115 throw new IOException("Illegal argument type"); 116 } 117 118 extensionValue = (byte[])value; 119 DerValue val = new DerValue(extensionValue); 120 if (val.tag != DerValue.tag_Sequence) { 121 throw new IOException("Invalid encoding for " + 122 "AuthorityInfoAccessExtension."); 123 } 124 accessDescriptions = new ArrayList<AccessDescription>(); 125 while (val.data.available() != 0) { 126 DerValue seq = val.data.getDerValue(); 127 AccessDescription accessDescription = new AccessDescription(seq); 128 accessDescriptions.add(accessDescription); 129 } 130 } 131 132 /** 133 * Return the list of AccessDescription objects. 134 */ getAccessDescriptions()135 public List<AccessDescription> getAccessDescriptions() { 136 return accessDescriptions; 137 } 138 139 /** 140 * Return the name of this attribute. 141 */ getName()142 public String getName() { 143 return NAME; 144 } 145 146 /** 147 * Write the extension to the DerOutputStream. 148 * 149 * @param out the DerOutputStream to write the extension to. 150 * @exception IOException on encoding errors. 151 */ encode(OutputStream out)152 public void encode(OutputStream out) throws IOException { 153 DerOutputStream tmp = new DerOutputStream(); 154 if (this.extensionValue == null) { 155 this.extensionId = PKIXExtensions.AuthInfoAccess_Id; 156 this.critical = false; 157 encodeThis(); 158 } 159 super.encode(tmp); 160 out.write(tmp.toByteArray()); 161 } 162 163 /** 164 * Set the attribute value. 165 */ 166 @SuppressWarnings("unchecked") // Checked with an instanceof check set(String name, Object obj)167 public void set(String name, Object obj) throws IOException { 168 if (name.equalsIgnoreCase(DESCRIPTIONS)) { 169 if (!(obj instanceof List)) { 170 throw new IOException("Attribute value should be of type List."); 171 } 172 accessDescriptions = (List<AccessDescription>)obj; 173 } else { 174 throw new IOException("Attribute name [" + name + 175 "] not recognized by " + 176 "CertAttrSet:AuthorityInfoAccessExtension."); 177 } 178 encodeThis(); 179 } 180 181 /** 182 * Get the attribute value. 183 */ get(String name)184 public List<AccessDescription> get(String name) throws IOException { 185 if (name.equalsIgnoreCase(DESCRIPTIONS)) { 186 return accessDescriptions; 187 } else { 188 throw new IOException("Attribute name [" + name + 189 "] not recognized by " + 190 "CertAttrSet:AuthorityInfoAccessExtension."); 191 } 192 } 193 194 /** 195 * Delete the attribute value. 196 */ delete(String name)197 public void delete(String name) throws IOException { 198 if (name.equalsIgnoreCase(DESCRIPTIONS)) { 199 accessDescriptions = new ArrayList<AccessDescription>(); 200 } else { 201 throw new IOException("Attribute name [" + name + 202 "] not recognized by " + 203 "CertAttrSet:AuthorityInfoAccessExtension."); 204 } 205 encodeThis(); 206 } 207 208 /** 209 * Return an enumeration of names of attributes existing within this 210 * attribute. 211 */ getElements()212 public Enumeration<String> getElements() { 213 AttributeNameEnumeration elements = new AttributeNameEnumeration(); 214 elements.addElement(DESCRIPTIONS); 215 return elements.elements(); 216 } 217 218 // Encode this extension value encodeThis()219 private void encodeThis() throws IOException { 220 if (accessDescriptions.isEmpty()) { 221 this.extensionValue = null; 222 } else { 223 DerOutputStream ads = new DerOutputStream(); 224 for (AccessDescription accessDescription : accessDescriptions) { 225 accessDescription.encode(ads); 226 } 227 DerOutputStream seq = new DerOutputStream(); 228 seq.write(DerValue.tag_Sequence, ads); 229 this.extensionValue = seq.toByteArray(); 230 } 231 } 232 233 /** 234 * Return the extension as user readable string. 235 */ toString()236 public String toString() { 237 return super.toString() + "AuthorityInfoAccess [\n " 238 + accessDescriptions + "\n]\n"; 239 } 240 241 } 242