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