jdk/src/share/classes/sun/security/x509/BasicConstraintsExtension.java
changeset 2 90ce3da70b43
child 2066 4230d224f27b
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1997-2006 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.security.x509;
       
    27 
       
    28 import java.io.IOException;
       
    29 import java.io.OutputStream;
       
    30 import java.util.Enumeration;
       
    31 
       
    32 import sun.security.util.*;
       
    33 
       
    34 /**
       
    35  * This class represents the Basic Constraints Extension.
       
    36  *
       
    37  * <p>The basic constraints extension identifies whether the subject of the
       
    38  * certificate is a CA and how deep a certification path may exist
       
    39  * through that CA.
       
    40  *
       
    41  * <pre>
       
    42  * The ASN.1 syntax for this extension is:
       
    43  * BasicConstraints ::= SEQUENCE {
       
    44  *     cA                BOOLEAN DEFAULT FALSE,
       
    45  *     pathLenConstraint INTEGER (0..MAX) OPTIONAL
       
    46  * }
       
    47  * </pre>
       
    48  * @author Amit Kapoor
       
    49  * @author Hemma Prafullchandra
       
    50  * @see CertAttrSet
       
    51  * @see Extension
       
    52  */
       
    53 public class BasicConstraintsExtension extends Extension
       
    54 implements CertAttrSet<String> {
       
    55     /**
       
    56      * Identifier for this attribute, to be used with the
       
    57      * get, set, delete methods of Certificate, x509 type.
       
    58      */
       
    59     public static final String IDENT = "x509.info.extensions.BasicConstraints";
       
    60     /**
       
    61      * Attribute names.
       
    62      */
       
    63     public static final String NAME = "BasicConstraints";
       
    64     public static final String IS_CA = "is_ca";
       
    65     public static final String PATH_LEN = "path_len";
       
    66 
       
    67     // Private data members
       
    68     private boolean     ca = false;
       
    69     private int pathLen = -1;
       
    70 
       
    71     // Encode this extension value
       
    72     private void encodeThis() throws IOException {
       
    73         if (ca == false && pathLen < 0) {
       
    74             this.extensionValue = null;
       
    75             return;
       
    76         }
       
    77         DerOutputStream out = new DerOutputStream();
       
    78         DerOutputStream tmp = new DerOutputStream();
       
    79 
       
    80         if (ca) {
       
    81             tmp.putBoolean(ca);
       
    82         }
       
    83         if (pathLen >= 0) {
       
    84             tmp.putInteger(pathLen);
       
    85         }
       
    86         out.write(DerValue.tag_Sequence, tmp);
       
    87         this.extensionValue = out.toByteArray();
       
    88     }
       
    89 
       
    90     /**
       
    91      * Default constructor for this object. The extension is marked
       
    92      * critical if the ca flag is true, false otherwise.
       
    93      *
       
    94      * @param ca true, if the subject of the Certificate is a CA.
       
    95      * @param len specifies the depth of the certification path.
       
    96      */
       
    97     public BasicConstraintsExtension(boolean ca, int len) throws IOException {
       
    98         this(Boolean.valueOf(ca), ca, len);
       
    99     }
       
   100 
       
   101     /**
       
   102      * Constructor for this object with specified criticality.
       
   103      *
       
   104      * @param critical true, if the extension should be marked critical
       
   105      * @param ca true, if the subject of the Certificate is a CA.
       
   106      * @param len specifies the depth of the certification path.
       
   107      */
       
   108     public BasicConstraintsExtension(Boolean critical, boolean ca, int len)
       
   109     throws IOException {
       
   110         this.ca = ca;
       
   111         this.pathLen = len;
       
   112         this.extensionId = PKIXExtensions.BasicConstraints_Id;
       
   113         this.critical = critical.booleanValue();
       
   114         encodeThis();
       
   115     }
       
   116 
       
   117     /**
       
   118      * Create the extension from the passed DER encoded value of the same.
       
   119      *
       
   120      * @param critical flag indicating if extension is critical or not
       
   121      * @param value an array containing the DER encoded bytes of the extension.
       
   122      * @exception ClassCastException if value is not an array of bytes
       
   123      * @exception IOException on error.
       
   124      */
       
   125      public BasicConstraintsExtension(Boolean critical, Object value)
       
   126          throws IOException
       
   127     {
       
   128          this.extensionId = PKIXExtensions.BasicConstraints_Id;
       
   129          this.critical = critical.booleanValue();
       
   130 
       
   131          this.extensionValue = (byte[]) value;
       
   132          DerValue val = new DerValue(this.extensionValue);
       
   133          if (val.tag != DerValue.tag_Sequence) {
       
   134              throw new IOException("Invalid encoding of BasicConstraints");
       
   135          }
       
   136 
       
   137          if (val.data == null) {
       
   138              // non-CA cert ("cA" field is FALSE by default), return -1
       
   139              return;
       
   140          }
       
   141          DerValue opt = val.data.getDerValue();
       
   142          if (opt.tag != DerValue.tag_Boolean) {
       
   143              // non-CA cert ("cA" field is FALSE by default), return -1
       
   144              return;
       
   145          }
       
   146 
       
   147          this.ca = opt.getBoolean();
       
   148          if (val.data.available() == 0) {
       
   149              // From PKIX profile:
       
   150              // Where pathLenConstraint does not appear, there is no
       
   151              // limit to the allowed length of the certification path.
       
   152              this.pathLen = Integer.MAX_VALUE;
       
   153              return;
       
   154          }
       
   155 
       
   156          opt = val.data.getDerValue();
       
   157          if (opt.tag != DerValue.tag_Integer) {
       
   158              throw new IOException("Invalid encoding of BasicConstraints");
       
   159          }
       
   160          this.pathLen = opt.getInteger();
       
   161          /*
       
   162           * Activate this check once again after PKIX profiling
       
   163           * is a standard and this check no longer imposes an
       
   164           * interoperability barrier.
       
   165           * if (ca) {
       
   166           *   if (!this.critical) {
       
   167           *   throw new IOException("Criticality cannot be false for CA.");
       
   168           *   }
       
   169           * }
       
   170           */
       
   171      }
       
   172 
       
   173      /**
       
   174       * Return user readable form of extension.
       
   175       */
       
   176      public String toString() {
       
   177          String s = super.toString() + "BasicConstraints:[\n";
       
   178 
       
   179          s += ((ca) ? ("  CA:true") : ("  CA:false")) + "\n";
       
   180          if (pathLen >= 0) {
       
   181              s += "  PathLen:" + pathLen + "\n";
       
   182          } else {
       
   183              s += "  PathLen: undefined\n";
       
   184          }
       
   185          return (s + "]\n");
       
   186      }
       
   187 
       
   188      /**
       
   189       * Encode this extension value to the output stream.
       
   190       *
       
   191       * @param out the DerOutputStream to encode the extension to.
       
   192       */
       
   193      public void encode(OutputStream out) throws IOException {
       
   194          DerOutputStream tmp = new DerOutputStream();
       
   195          if (extensionValue == null) {
       
   196              this.extensionId = PKIXExtensions.BasicConstraints_Id;
       
   197              if (ca) {
       
   198                  critical = true;
       
   199              } else {
       
   200                  critical = false;
       
   201              }
       
   202              encodeThis();
       
   203          }
       
   204          super.encode(tmp);
       
   205 
       
   206          out.write(tmp.toByteArray());
       
   207      }
       
   208 
       
   209     /**
       
   210      * Set the attribute value.
       
   211      */
       
   212     public void set(String name, Object obj) throws IOException {
       
   213         if (name.equalsIgnoreCase(IS_CA)) {
       
   214             if (!(obj instanceof Boolean)) {
       
   215               throw new IOException("Attribute value should be of type Boolean.");
       
   216             }
       
   217             ca = ((Boolean)obj).booleanValue();
       
   218         } else if (name.equalsIgnoreCase(PATH_LEN)) {
       
   219             if (!(obj instanceof Integer)) {
       
   220               throw new IOException("Attribute value should be of type Integer.");
       
   221             }
       
   222             pathLen = ((Integer)obj).intValue();
       
   223         } else {
       
   224           throw new IOException("Attribute name not recognized by " +
       
   225                                 "CertAttrSet:BasicConstraints.");
       
   226         }
       
   227         encodeThis();
       
   228     }
       
   229 
       
   230     /**
       
   231      * Get the attribute value.
       
   232      */
       
   233     public Object get(String name) throws IOException {
       
   234         if (name.equalsIgnoreCase(IS_CA)) {
       
   235             return (Boolean.valueOf(ca));
       
   236         } else if (name.equalsIgnoreCase(PATH_LEN)) {
       
   237             return (Integer.valueOf(pathLen));
       
   238         } else {
       
   239           throw new IOException("Attribute name not recognized by " +
       
   240                                 "CertAttrSet:BasicConstraints.");
       
   241         }
       
   242     }
       
   243 
       
   244     /**
       
   245      * Delete the attribute value.
       
   246      */
       
   247     public void delete(String name) throws IOException {
       
   248         if (name.equalsIgnoreCase(IS_CA)) {
       
   249             ca = false;
       
   250         } else if (name.equalsIgnoreCase(PATH_LEN)) {
       
   251             pathLen = -1;
       
   252         } else {
       
   253           throw new IOException("Attribute name not recognized by " +
       
   254                                 "CertAttrSet:BasicConstraints.");
       
   255         }
       
   256         encodeThis();
       
   257     }
       
   258 
       
   259     /**
       
   260      * Return an enumeration of names of attributes existing within this
       
   261      * attribute.
       
   262      */
       
   263     public Enumeration<String> getElements() {
       
   264         AttributeNameEnumeration elements = new AttributeNameEnumeration();
       
   265         elements.addElement(IS_CA);
       
   266         elements.addElement(PATH_LEN);
       
   267 
       
   268         return (elements.elements());
       
   269     }
       
   270 
       
   271     /**
       
   272      * Return the name of this attribute.
       
   273      */
       
   274     public String getName() {
       
   275         return (NAME);
       
   276     }
       
   277 }