Path: blob/master/src/java.base/share/classes/sun/security/x509/BasicConstraintsExtension.java
41159 views
/*1* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.x509;2627import java.io.IOException;28import java.io.OutputStream;29import java.util.Enumeration;3031import sun.security.util.*;3233/**34* This class represents the Basic Constraints Extension.35*36* <p>The basic constraints extension identifies whether the subject of the37* certificate is a CA and how deep a certification path may exist38* through that CA.39*40* <pre>41* The ASN.1 syntax for this extension is:42* BasicConstraints ::= SEQUENCE {43* cA BOOLEAN DEFAULT FALSE,44* pathLenConstraint INTEGER (0..MAX) OPTIONAL45* }46* </pre>47* @author Amit Kapoor48* @author Hemma Prafullchandra49* @see CertAttrSet50* @see Extension51*/52public class BasicConstraintsExtension extends Extension53implements CertAttrSet<String> {54/**55* Identifier for this attribute, to be used with the56* get, set, delete methods of Certificate, x509 type.57*/58public static final String IDENT = "x509.info.extensions.BasicConstraints";59/**60* Attribute names.61*/62public static final String NAME = "BasicConstraints";63public static final String IS_CA = "is_ca";64public static final String PATH_LEN = "path_len";6566// Private data members67private boolean ca = false;68private int pathLen = -1;6970// Encode this extension value71private void encodeThis() throws IOException {72DerOutputStream out = new DerOutputStream();73DerOutputStream tmp = new DerOutputStream();7475if (ca) {76tmp.putBoolean(ca);77// Only encode pathLen when ca == true78if (pathLen >= 0) {79tmp.putInteger(pathLen);80}81}82out.write(DerValue.tag_Sequence, tmp);83this.extensionValue = out.toByteArray();84}8586/**87* Default constructor for this object. The extension is marked88* critical if the ca flag is true, false otherwise.89*90* @param ca true, if the subject of the Certificate is a CA.91* @param len specifies the depth of the certification path.92*/93public BasicConstraintsExtension(boolean ca, int len) throws IOException {94this(Boolean.valueOf(ca), ca, len);95}9697/**98* Constructor for this object with specified criticality.99*100* @param critical true, if the extension should be marked critical101* @param ca true, if the subject of the Certificate is a CA.102* @param len specifies the depth of the certification path.103*/104public BasicConstraintsExtension(Boolean critical, boolean ca, int len)105throws IOException {106this.ca = ca;107this.pathLen = len;108this.extensionId = PKIXExtensions.BasicConstraints_Id;109this.critical = critical.booleanValue();110encodeThis();111}112113/**114* Create the extension from the passed DER encoded value of the same.115*116* @param critical flag indicating if extension is critical or not117* @param value an array containing the DER encoded bytes of the extension.118* @exception ClassCastException if value is not an array of bytes119* @exception IOException on error.120*/121public BasicConstraintsExtension(Boolean critical, Object value)122throws IOException123{124this.extensionId = PKIXExtensions.BasicConstraints_Id;125this.critical = critical.booleanValue();126127this.extensionValue = (byte[]) value;128DerValue val = new DerValue(this.extensionValue);129if (val.tag != DerValue.tag_Sequence) {130throw new IOException("Invalid encoding of BasicConstraints");131}132133if (val.data == null || val.data.available() == 0) {134// non-CA cert ("cA" field is FALSE by default), return -1135return;136}137DerValue opt = val.data.getDerValue();138if (opt.tag != DerValue.tag_Boolean) {139// non-CA cert ("cA" field is FALSE by default), return -1140return;141}142143this.ca = opt.getBoolean();144if (val.data.available() == 0) {145// From PKIX profile:146// Where pathLenConstraint does not appear, there is no147// limit to the allowed length of the certification path.148this.pathLen = Integer.MAX_VALUE;149return;150}151152opt = val.data.getDerValue();153if (opt.tag != DerValue.tag_Integer) {154throw new IOException("Invalid encoding of BasicConstraints");155}156this.pathLen = opt.getInteger();157/*158* Activate this check once again after PKIX profiling159* is a standard and this check no longer imposes an160* interoperability barrier.161* if (ca) {162* if (!this.critical) {163* throw new IOException("Criticality cannot be false for CA.");164* }165* }166*/167}168169/**170* Return user readable form of extension.171*/172public String toString() {173String pathLenAsString;174if (pathLen < 0) {175pathLenAsString = " undefined";176} else if (pathLen == Integer.MAX_VALUE) {177pathLenAsString = " no limit";178} else {179pathLenAsString = String.valueOf(pathLen);180}181return super.toString() +182"BasicConstraints:[\n CA:" + ca +183"\n PathLen:" + pathLenAsString +184"\n]\n";185}186187/**188* Encode this extension value to the output stream.189*190* @param out the DerOutputStream to encode the extension to.191*/192public void encode(OutputStream out) throws IOException {193DerOutputStream tmp = new DerOutputStream();194if (extensionValue == null) {195this.extensionId = PKIXExtensions.BasicConstraints_Id;196if (ca) {197critical = true;198} else {199critical = false;200}201encodeThis();202}203super.encode(tmp);204205out.write(tmp.toByteArray());206}207208/**209* Set the attribute value.210*/211public void set(String name, Object obj) throws IOException {212if (name.equalsIgnoreCase(IS_CA)) {213if (!(obj instanceof Boolean)) {214throw new IOException("Attribute value should be of type Boolean.");215}216ca = ((Boolean)obj).booleanValue();217} else if (name.equalsIgnoreCase(PATH_LEN)) {218if (!(obj instanceof Integer)) {219throw new IOException("Attribute value should be of type Integer.");220}221pathLen = ((Integer)obj).intValue();222} else {223throw new IOException("Attribute name not recognized by " +224"CertAttrSet:BasicConstraints.");225}226encodeThis();227}228229/**230* Get the attribute value.231*/232public Object get(String name) throws IOException {233if (name.equalsIgnoreCase(IS_CA)) {234return (Boolean.valueOf(ca));235} else if (name.equalsIgnoreCase(PATH_LEN)) {236return (Integer.valueOf(pathLen));237} else {238throw new IOException("Attribute name not recognized by " +239"CertAttrSet:BasicConstraints.");240}241}242243/**244* Delete the attribute value.245*/246public void delete(String name) throws IOException {247if (name.equalsIgnoreCase(IS_CA)) {248ca = false;249} else if (name.equalsIgnoreCase(PATH_LEN)) {250pathLen = -1;251} else {252throw new IOException("Attribute name not recognized by " +253"CertAttrSet:BasicConstraints.");254}255encodeThis();256}257258/**259* Return an enumeration of names of attributes existing within this260* attribute.261*/262public Enumeration<String> getElements() {263AttributeNameEnumeration elements = new AttributeNameEnumeration();264elements.addElement(IS_CA);265elements.addElement(PATH_LEN);266267return (elements.elements());268}269270/**271* Return the name of this attribute.272*/273public String getName() {274return (NAME);275}276}277278279