0N/A/*
2362N/A * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.x509;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.OutputStream;
0N/Aimport java.util.Enumeration;
0N/A
0N/Aimport sun.security.util.*;
0N/A
0N/A/**
0N/A * This class represents the Basic Constraints Extension.
0N/A *
0N/A * <p>The basic constraints extension identifies whether the subject of the
0N/A * certificate is a CA and how deep a certification path may exist
0N/A * through that CA.
0N/A *
0N/A * <pre>
0N/A * The ASN.1 syntax for this extension is:
0N/A * BasicConstraints ::= SEQUENCE {
0N/A * cA BOOLEAN DEFAULT FALSE,
0N/A * pathLenConstraint INTEGER (0..MAX) OPTIONAL
0N/A * }
0N/A * </pre>
0N/A * @author Amit Kapoor
0N/A * @author Hemma Prafullchandra
0N/A * @see CertAttrSet
0N/A * @see Extension
0N/A */
0N/Apublic class BasicConstraintsExtension extends Extension
0N/Aimplements CertAttrSet<String> {
0N/A /**
0N/A * Identifier for this attribute, to be used with the
0N/A * get, set, delete methods of Certificate, x509 type.
0N/A */
0N/A public static final String IDENT = "x509.info.extensions.BasicConstraints";
0N/A /**
0N/A * Attribute names.
0N/A */
0N/A public static final String NAME = "BasicConstraints";
0N/A public static final String IS_CA = "is_ca";
0N/A public static final String PATH_LEN = "path_len";
0N/A
0N/A // Private data members
0N/A private boolean ca = false;
0N/A private int pathLen = -1;
0N/A
0N/A // Encode this extension value
0N/A private void encodeThis() throws IOException {
0N/A DerOutputStream out = new DerOutputStream();
0N/A DerOutputStream tmp = new DerOutputStream();
0N/A
0N/A if (ca) {
0N/A tmp.putBoolean(ca);
902N/A // Only encode pathLen when ca == true
902N/A if (pathLen >= 0) {
902N/A tmp.putInteger(pathLen);
902N/A }
0N/A }
0N/A out.write(DerValue.tag_Sequence, tmp);
0N/A this.extensionValue = out.toByteArray();
0N/A }
0N/A
0N/A /**
0N/A * Default constructor for this object. The extension is marked
0N/A * critical if the ca flag is true, false otherwise.
0N/A *
0N/A * @param ca true, if the subject of the Certificate is a CA.
0N/A * @param len specifies the depth of the certification path.
0N/A */
0N/A public BasicConstraintsExtension(boolean ca, int len) throws IOException {
0N/A this(Boolean.valueOf(ca), ca, len);
0N/A }
0N/A
0N/A /**
0N/A * Constructor for this object with specified criticality.
0N/A *
0N/A * @param critical true, if the extension should be marked critical
0N/A * @param ca true, if the subject of the Certificate is a CA.
0N/A * @param len specifies the depth of the certification path.
0N/A */
0N/A public BasicConstraintsExtension(Boolean critical, boolean ca, int len)
0N/A throws IOException {
0N/A this.ca = ca;
0N/A this.pathLen = len;
0N/A this.extensionId = PKIXExtensions.BasicConstraints_Id;
0N/A this.critical = critical.booleanValue();
0N/A encodeThis();
0N/A }
0N/A
0N/A /**
0N/A * Create the extension from the passed DER encoded value of the same.
0N/A *
0N/A * @param critical flag indicating if extension is critical or not
0N/A * @param value an array containing the DER encoded bytes of the extension.
0N/A * @exception ClassCastException if value is not an array of bytes
0N/A * @exception IOException on error.
0N/A */
0N/A public BasicConstraintsExtension(Boolean critical, Object value)
0N/A throws IOException
0N/A {
0N/A this.extensionId = PKIXExtensions.BasicConstraints_Id;
0N/A this.critical = critical.booleanValue();
0N/A
0N/A this.extensionValue = (byte[]) value;
0N/A DerValue val = new DerValue(this.extensionValue);
0N/A if (val.tag != DerValue.tag_Sequence) {
0N/A throw new IOException("Invalid encoding of BasicConstraints");
0N/A }
0N/A
902N/A if (val.data == null || val.data.available() == 0) {
0N/A // non-CA cert ("cA" field is FALSE by default), return -1
0N/A return;
0N/A }
0N/A DerValue opt = val.data.getDerValue();
0N/A if (opt.tag != DerValue.tag_Boolean) {
0N/A // non-CA cert ("cA" field is FALSE by default), return -1
0N/A return;
0N/A }
0N/A
0N/A this.ca = opt.getBoolean();
0N/A if (val.data.available() == 0) {
0N/A // From PKIX profile:
0N/A // Where pathLenConstraint does not appear, there is no
0N/A // limit to the allowed length of the certification path.
0N/A this.pathLen = Integer.MAX_VALUE;
0N/A return;
0N/A }
0N/A
0N/A opt = val.data.getDerValue();
0N/A if (opt.tag != DerValue.tag_Integer) {
0N/A throw new IOException("Invalid encoding of BasicConstraints");
0N/A }
0N/A this.pathLen = opt.getInteger();
0N/A /*
0N/A * Activate this check once again after PKIX profiling
0N/A * is a standard and this check no longer imposes an
0N/A * interoperability barrier.
0N/A * if (ca) {
0N/A * if (!this.critical) {
0N/A * throw new IOException("Criticality cannot be false for CA.");
0N/A * }
0N/A * }
0N/A */
0N/A }
0N/A
0N/A /**
0N/A * Return user readable form of extension.
0N/A */
0N/A public String toString() {
0N/A String s = super.toString() + "BasicConstraints:[\n";
0N/A
0N/A s += ((ca) ? (" CA:true") : (" CA:false")) + "\n";
0N/A if (pathLen >= 0) {
0N/A s += " PathLen:" + pathLen + "\n";
0N/A } else {
0N/A s += " PathLen: undefined\n";
0N/A }
0N/A return (s + "]\n");
0N/A }
0N/A
0N/A /**
0N/A * Encode this extension value to the output stream.
0N/A *
0N/A * @param out the DerOutputStream to encode the extension to.
0N/A */
0N/A public void encode(OutputStream out) throws IOException {
0N/A DerOutputStream tmp = new DerOutputStream();
0N/A if (extensionValue == null) {
0N/A this.extensionId = PKIXExtensions.BasicConstraints_Id;
0N/A if (ca) {
0N/A critical = true;
0N/A } else {
0N/A critical = false;
0N/A }
0N/A encodeThis();
0N/A }
0N/A super.encode(tmp);
0N/A
0N/A out.write(tmp.toByteArray());
0N/A }
0N/A
0N/A /**
0N/A * Set the attribute value.
0N/A */
0N/A public void set(String name, Object obj) throws IOException {
0N/A if (name.equalsIgnoreCase(IS_CA)) {
0N/A if (!(obj instanceof Boolean)) {
0N/A throw new IOException("Attribute value should be of type Boolean.");
0N/A }
0N/A ca = ((Boolean)obj).booleanValue();
0N/A } else if (name.equalsIgnoreCase(PATH_LEN)) {
0N/A if (!(obj instanceof Integer)) {
0N/A throw new IOException("Attribute value should be of type Integer.");
0N/A }
0N/A pathLen = ((Integer)obj).intValue();
0N/A } else {
0N/A throw new IOException("Attribute name not recognized by " +
0N/A "CertAttrSet:BasicConstraints.");
0N/A }
0N/A encodeThis();
0N/A }
0N/A
0N/A /**
0N/A * Get the attribute value.
0N/A */
0N/A public Object get(String name) throws IOException {
0N/A if (name.equalsIgnoreCase(IS_CA)) {
0N/A return (Boolean.valueOf(ca));
0N/A } else if (name.equalsIgnoreCase(PATH_LEN)) {
0N/A return (Integer.valueOf(pathLen));
0N/A } else {
0N/A throw new IOException("Attribute name not recognized by " +
0N/A "CertAttrSet:BasicConstraints.");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Delete the attribute value.
0N/A */
0N/A public void delete(String name) throws IOException {
0N/A if (name.equalsIgnoreCase(IS_CA)) {
0N/A ca = false;
0N/A } else if (name.equalsIgnoreCase(PATH_LEN)) {
0N/A pathLen = -1;
0N/A } else {
0N/A throw new IOException("Attribute name not recognized by " +
0N/A "CertAttrSet:BasicConstraints.");
0N/A }
0N/A encodeThis();
0N/A }
0N/A
0N/A /**
0N/A * Return an enumeration of names of attributes existing within this
0N/A * attribute.
0N/A */
0N/A public Enumeration<String> getElements() {
0N/A AttributeNameEnumeration elements = new AttributeNameEnumeration();
0N/A elements.addElement(IS_CA);
0N/A elements.addElement(PATH_LEN);
0N/A
0N/A return (elements.elements());
0N/A }
0N/A
0N/A /**
0N/A * Return the name of this attribute.
0N/A */
0N/A public String getName() {
0N/A return (NAME);
0N/A }
0N/A}