001package org.apache.commons.ssl.org.bouncycastle.asn1.x509;
002
003import java.math.BigInteger;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Boolean;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
012import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
013
014public class BasicConstraints
015    extends ASN1Object
016{
017    ASN1Boolean  cA = ASN1Boolean.getInstance(false);
018    ASN1Integer  pathLenConstraint = null;
019
020    public static BasicConstraints getInstance(
021        ASN1TaggedObject obj,
022        boolean          explicit)
023    {
024        return getInstance(ASN1Sequence.getInstance(obj, explicit));
025    }
026
027    public static BasicConstraints getInstance(
028        Object  obj)
029    {
030        if (obj instanceof BasicConstraints)
031        {
032            return (BasicConstraints)obj;
033        }
034        if (obj instanceof X509Extension)
035        {
036            return getInstance(X509Extension.convertValueToObject((X509Extension)obj));
037        }
038        if (obj != null)
039        {
040            return new BasicConstraints(ASN1Sequence.getInstance(obj));
041        }
042
043        return null;
044    }
045
046    public static BasicConstraints fromExtensions(Extensions extensions)
047    {
048        return BasicConstraints.getInstance(extensions.getExtensionParsedValue(Extension.basicConstraints));
049    }
050
051    private BasicConstraints(
052        ASN1Sequence   seq)
053    {
054        if (seq.size() == 0)
055        {
056            this.cA = null;
057            this.pathLenConstraint = null;
058        }
059        else
060        {
061            if (seq.getObjectAt(0) instanceof ASN1Boolean)
062            {
063                this.cA = ASN1Boolean.getInstance(seq.getObjectAt(0));
064            }
065            else
066            {
067                this.cA = null;
068                this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(0));
069            }
070            if (seq.size() > 1)
071            {
072                if (this.cA != null)
073                {
074                    this.pathLenConstraint = ASN1Integer.getInstance(seq.getObjectAt(1));
075                }
076                else
077                {
078                    throw new IllegalArgumentException("wrong sequence in constructor");
079                }
080            }
081        }
082    }
083
084    public BasicConstraints(
085        boolean cA)
086    {
087        if (cA)
088        {
089            this.cA = ASN1Boolean.getInstance(true);
090        }
091        else
092        {
093            this.cA = null;
094        }
095        this.pathLenConstraint = null;
096    }
097
098    /**
099     * create a cA=true object for the given path length constraint.
100     * 
101     * @param pathLenConstraint
102     */
103    public BasicConstraints(
104        int     pathLenConstraint)
105    {
106        this.cA = ASN1Boolean.getInstance(true);
107        this.pathLenConstraint = new ASN1Integer(pathLenConstraint);
108    }
109
110    public boolean isCA()
111    {
112        return (cA != null) && cA.isTrue();
113    }
114
115    public BigInteger getPathLenConstraint()
116    {
117        if (pathLenConstraint != null)
118        {
119            return pathLenConstraint.getValue();
120        }
121
122        return null;
123    }
124
125    /**
126     * Produce an object suitable for an ASN1OutputStream.
127     * <pre>
128     * BasicConstraints := SEQUENCE {
129     *    cA                  BOOLEAN DEFAULT FALSE,
130     *    pathLenConstraint   INTEGER (0..MAX) OPTIONAL
131     * }
132     * </pre>
133     */
134    public ASN1Primitive toASN1Primitive()
135    {
136        ASN1EncodableVector  v = new ASN1EncodableVector();
137
138        if (cA != null)
139        {
140            v.add(cA);
141        }
142
143        if (pathLenConstraint != null)  // yes some people actually do this when cA is false...
144        {
145            v.add(pathLenConstraint);
146        }
147
148        return new DERSequence(v);
149    }
150
151    public String toString()
152    {
153        if (pathLenConstraint == null)
154        {
155            if (cA == null)
156            {
157                return "BasicConstraints: isCa(false)";
158            }
159            return "BasicConstraints: isCa(" + this.isCA() + ")";
160        }
161        return "BasicConstraints: isCa(" + this.isCA() + "), pathLenConstraint = " + pathLenConstraint.getValue();
162    }
163}