001    /**
002     *
003     *  Licensed to the Apache Software Foundation (ASF) under one or more
004     *  contributor license agreements.  See the NOTICE file distributed with
005     *  this work for additional information regarding copyright ownership.
006     *  The ASF licenses this file to You under the Apache License, Version 2.0
007     *  (the "License"); you may not use this file except in compliance with
008     *  the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     *  Unless required by applicable law or agreed to in writing, software
013     *  distributed under the License is distributed on an "AS IS" BASIS,
014     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     *  See the License for the specific language governing permissions and
016     *  limitations under the License.
017     */
018    
019    package org.apache.geronimo.util.asn1.x509;
020    
021    import org.apache.geronimo.util.asn1.ASN1Choice;
022    import org.apache.geronimo.util.asn1.ASN1Encodable;
023    import org.apache.geronimo.util.asn1.ASN1OctetString;
024    import org.apache.geronimo.util.asn1.ASN1Sequence;
025    import org.apache.geronimo.util.asn1.ASN1TaggedObject;
026    import org.apache.geronimo.util.asn1.DEREncodable;
027    import org.apache.geronimo.util.asn1.DERIA5String;
028    import org.apache.geronimo.util.asn1.DERObject;
029    import org.apache.geronimo.util.asn1.DERObjectIdentifier;
030    import org.apache.geronimo.util.asn1.DERTaggedObject;
031    
032    /**
033     * The GeneralName object.
034     * <pre>
035     * GeneralName ::= CHOICE {
036     *      otherName                       [0]     OtherName,
037     *      rfc822Name                      [1]     IA5String,
038     *      dNSName                         [2]     IA5String,
039     *      x400Address                     [3]     ORAddress,
040     *      directoryName                   [4]     Name,
041     *      ediPartyName                    [5]     EDIPartyName,
042     *      uniformResourceIdentifier       [6]     IA5String,
043     *      iPAddress                       [7]     OCTET STRING,
044     *      registeredID                    [8]     OBJECT IDENTIFIER}
045     *
046     * OtherName ::= SEQUENCE {
047     *      type-id    OBJECT IDENTIFIER,
048     *      value      [0] EXPLICIT ANY DEFINED BY type-id }
049     *
050     * EDIPartyName ::= SEQUENCE {
051     *      nameAssigner            [0]     DirectoryString OPTIONAL,
052     *      partyName               [1]     DirectoryString }
053     *
054     * Name ::= CHOICE { RDNSequence }
055     * </pre>
056     */
057    public class GeneralName
058        extends ASN1Encodable
059        implements ASN1Choice
060    {
061        public static final int otherName                     = 0;
062        public static final int rfc822Name                    = 1;
063        public static final int dNSName                       = 2;
064        public static final int x400Address                   = 3;
065        public static final int directoryName                 = 4;
066        public static final int ediPartyName                  = 5;
067        public static final int uniformResourceIdentifier     = 6;
068        public static final int iPAddress                     = 7;
069        public static final int registeredID                  = 8;
070    
071        DEREncodable      obj;
072        int               tag;
073    
074        public GeneralName(
075            X509Name  dirName)
076        {
077            this.obj = dirName;
078            this.tag = 4;
079        }
080    
081        /**
082         * @deprecated this constructor seems the wrong way round! Use GeneralName(tag, name).
083         */
084        public GeneralName(
085            DERObject name, int tag)
086        {
087            this.obj = name;
088            this.tag = tag;
089        }
090    
091        /**
092         * When the subjectAltName extension contains an Internet mail address,
093         * the address MUST be included as an rfc822Name. The format of an
094         * rfc822Name is an "addr-spec" as defined in RFC 822 [RFC 822].
095         *
096         * When the subjectAltName extension contains a domain name service
097         * label, the domain name MUST be stored in the dNSName (an IA5String).
098         * The name MUST be in the "preferred name syntax," as specified by RFC
099         * 1034 [RFC 1034].
100         *
101         * When the subjectAltName extension contains a URI, the name MUST be
102         * stored in the uniformResourceIdentifier (an IA5String). The name MUST
103         * be a non-relative URL, and MUST follow the URL syntax and encoding
104         * rules specified in [RFC 1738].  The name must include both a scheme
105         * (e.g., "http" or "ftp") and a scheme-specific-part.  The scheme-
106         * specific-part must include a fully qualified domain name or IP
107         * address as the host.
108         *
109         * When the subjectAltName extension contains a iPAddress, the address
110         * MUST be stored in the octet string in "network byte order," as
111         * specified in RFC 791 [RFC 791]. The least significant bit (LSB) of
112         * each octet is the LSB of the corresponding byte in the network
113         * address. For IP Version 4, as specified in RFC 791, the octet string
114         * MUST contain exactly four octets.  For IP Version 6, as specified in
115         * RFC 1883, the octet string MUST contain exactly sixteen octets [RFC
116         * 1883].
117         */
118        public GeneralName(
119            int           tag,
120            ASN1Encodable name)
121        {
122            this.obj = name;
123            this.tag = tag;
124        }
125    
126        /**
127         * Create a General name for the given tag from the passed in String.
128         *
129         * @param tag tag number
130         * @param name string representation of name
131         */
132        public GeneralName(
133            int       tag,
134            String    name)
135        {
136            if (tag == rfc822Name || tag == dNSName || tag == uniformResourceIdentifier)
137            {
138                this.tag = tag;
139                this.obj = new DERIA5String(name);
140            }
141            else if (tag == registeredID)
142            {
143                this.tag = tag;
144                this.obj = new DERObjectIdentifier(name);
145            }
146            else
147            {
148                throw new IllegalArgumentException("can't process String for tag: " + tag);
149            }
150        }
151    
152        public static GeneralName getInstance(
153            Object obj)
154        {
155            if (obj == null || obj instanceof GeneralName)
156            {
157                return (GeneralName)obj;
158            }
159    
160            if (obj instanceof ASN1TaggedObject)
161            {
162                ASN1TaggedObject    tagObj = (ASN1TaggedObject)obj;
163                int                 tag = tagObj.getTagNo();
164    
165                switch (tag)
166                {
167                case otherName:
168                    return new GeneralName(ASN1Sequence.getInstance(tagObj, false), tag);
169                case rfc822Name:
170                    return new GeneralName(DERIA5String.getInstance(tagObj, false), tag);
171                case dNSName:
172                    return new GeneralName(DERIA5String.getInstance(tagObj, false), tag);
173                case x400Address:
174                    throw new IllegalArgumentException("unknown tag: " + tag);
175                case directoryName:
176                    return new GeneralName(ASN1Sequence.getInstance(tagObj, true), tag);
177                case ediPartyName:
178                    return new GeneralName(ASN1Sequence.getInstance(tagObj, false), tag);
179                case uniformResourceIdentifier:
180                    return new GeneralName(DERIA5String.getInstance(tagObj, false), tag);
181                case iPAddress:
182                    return new GeneralName(ASN1OctetString.getInstance(tagObj, false), tag);
183                case registeredID:
184                    return new GeneralName(DERObjectIdentifier.getInstance(tagObj, false), tag);
185                }
186            }
187    
188            throw new IllegalArgumentException("unknown object in getInstance");
189        }
190    
191        public static GeneralName getInstance(
192            ASN1TaggedObject tagObj,
193            boolean          explicit)
194        {
195            return GeneralName.getInstance(ASN1TaggedObject.getInstance(tagObj, true));
196        }
197    
198        public int getTagNo()
199        {
200            return tag;
201        }
202    
203        public DEREncodable getName()
204        {
205            return obj;
206        }
207    
208        public DERObject toASN1Object()
209        {
210            if (tag == directoryName)       // directoryName is explicitly tagged as it is a CHOICE
211            {
212                return new DERTaggedObject(true, tag, obj);
213            }
214            else
215            {
216                return new DERTaggedObject(false, tag, obj);
217            }
218        }
219    }