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