1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* @author Vladimir N. Molotkov, Alexander Y. Kleymenov
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project* @version $Revision$
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project*/
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.security.x509;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
266ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilsonimport java.net.InetAddress;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URI;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URISyntaxException;
296ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilsonimport java.net.UnknownHostException;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays;
3228d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Rootimport java.util.Collection;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collections;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List;
35fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstromimport java.util.Locale;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.security.auth.x500.X500Principal;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Choice;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Implicit;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1OctetString;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Oid;
4128d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Rootimport org.apache.harmony.security.asn1.ASN1SequenceOf;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1StringType;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Type;
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.BerInputStream;
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ObjectIdentifier;
464b25199bc0b7a64a6feaa60e7d5d6b0474341234Elliott Hughesimport org.apache.harmony.security.utils.Array;
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.x501.Name;
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * The class encapsulates the ASN.1 DER encoding/decoding work
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * with the GeneralName structure which is a part of X.509 certificate
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (as specified in RFC 3280 -
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Internet X.509 Public Key Infrastructure.
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Certificate and Certificate Revocation List (CRL) Profile.
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  http://www.ietf.org/rfc/rfc3280.txt):
56f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre>
58f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   GeneralName::= CHOICE {
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        otherName                       [0]     OtherName,
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        rfc822Name                      [1]     IA5String,
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        dNSName                         [2]     IA5String,
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        x400Address                     [3]     ORAddress,
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        directoryName                   [4]     Name,
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        ediPartyName                    [5]     EDIPartyName,
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        uniformResourceIdentifier       [6]     IA5String,
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        iPAddress                       [7]     OCTET STRING,
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        registeredID                    [8]     OBJECT IDENTIFIER
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
70f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   OtherName::= SEQUENCE {
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        type-id    OBJECT IDENTIFIER,
73f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *        value      [0] EXPLICIT ANY DEFINED BY type-id
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
75f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   EDIPartyName::= SEQUENCE {
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        nameAssigner            [0]     DirectoryString OPTIONAL,
78f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *        partyName               [1]     DirectoryString
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
80f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   DirectoryString::= CHOICE {
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        teletexString             TeletexString   (SIZE (1..MAX)),
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        printableString           PrintableString (SIZE (1..MAX)),
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        universalString           UniversalString (SIZE (1..MAX)),
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        utf8String              UTF8String      (SIZE (1..MAX)),
86f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *        bmpString               BMPString       (SIZE (1..MAX))
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
88f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre>
90f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
916ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson * <p>This class doesn't support masked addresses like "10.9.8.0/255.255.255.0".
926ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson * These are only necessary for NameConstraints, which are not exposed in the
936ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson * Java certificate API.
946ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson *
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see org.apache.harmony.security.x509.NameConstraints
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see org.apache.harmony.security.x509.GeneralSubtree
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
985c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilsonpublic final class GeneralName {
99f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The values of the tags of fields
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int OTHER_NAME = 0;
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int RFC822_NAME = 1;
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int DNS_NAME = 2;
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int X400_ADDR = 3;
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int DIR_NAME = 4;
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int EDIP_NAME = 5;
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int UR_ID = 6;
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int IP_ADDR = 7;
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int REG_ID = 8;
112f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // ASN1 encoders/decoders for name choices
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static ASN1Type[] nameASN1 = new ASN1Type[9];
115f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static {
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[OTHER_NAME] = OtherName.ASN1;
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[RFC822_NAME] = ASN1StringType.IA5STRING;
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[DNS_NAME] = ASN1StringType.IA5STRING;
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[UR_ID] = ASN1StringType.IA5STRING;
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[X400_ADDR] = ORAddress.ASN1;
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[DIR_NAME] = Name.ASN1;
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[EDIP_NAME] = EDIPartyName.ASN1;
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[IP_ADDR] = ASN1OctetString.getInstance();
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[REG_ID] = ASN1Oid.getInstance();
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
127f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
1285c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson    /** the tag of the name type */
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int tag;
1305c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson    /** the name value (can be String or byte array) */
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Object name;
1325c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson    /** the ASN.1 encoded form of GeneralName */
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private byte[] encoding;
1345c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson    /** the ASN.1 encoded form of GeneralName's field */
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private byte[] name_encoding;
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Makes the GeneralName object from the tag type and corresponding
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * well established string representation of the name value.
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The String representation of [7] iPAddress is such as:
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  For IP v4, as specified in RFC 791, the address must
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  contain exactly 4 byte component.  For IP v6, as specified in
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  RFC 1883, the address must contain exactly 16 byte component.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  If GeneralName structure is used as a part of Name Constraints
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  extension, to represent an address range the number of address
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  component is doubled (to 8 and 32 bytes respectively).
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Note that the names:
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [0] otherName, [3] x400Address, [5] ediPartyName
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *   have no the string representation, so exception will be thrown.
150f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * To make the GeneralName object with such names use another constructor.
151f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @param tag is an integer which value corresponds to the name type.
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name is a name value corresponding to the tag.
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(int tag, String name) throws IOException {
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name == null) {
156897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("name == null");
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = tag;
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (tag) {
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME :
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR :
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME :
163897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Unknown string representation for type [" + tag + "]");
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME :
165f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // according to RFC 3280 p.34 the DNS name should be
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // checked against the
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // RFC 1034 p.10 (3.5. Preferred name syntax):
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                checkDNS(name);
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = name;
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID :
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check the uniformResourceIdentifier for correctness
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // according to RFC 3280 p.34
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                checkURI(name);
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = name;
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME :
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = name;
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = oidStrToInts(name);
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DIR_NAME :
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = new Name(name);
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case IP_ADDR :
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = ipStrToBytes(name);
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
190897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Unknown type: [" + tag + "]");
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(OtherName name) {
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = OTHER_NAME;
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(ORAddress name) {
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = X400_ADDR;
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(Name name) {
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = DIR_NAME;
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(EDIPartyName name) {
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = EDIP_NAME;
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
214f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Constructor for type [7] iPAddress.
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * name is an array of bytes such as:
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  For IP v4, as specified in RFC 791, the address must
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  contain exactly 4 byte component.  For IP v6, as specified in
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  RFC 1883, the address must contain exactly 16 byte component.
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  If GeneralName structure is used as a part of Name Constraints
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  extension, to represent an address range the number of address
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  component is doubled (to 8 and 32 bytes respectively).
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(byte[] name) throws IllegalArgumentException {
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = IP_ADDR;
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = new byte[name.length];
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.arraycopy(name, 0, this.name, 0, name.length);
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an object representing the value of GeneralName.
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param tag is an integer which value corresponds
232f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * to the name type (0-8),
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name is a DER encoded for of the name value
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
235897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes    public GeneralName(int tag, byte[] name) throws IOException {
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name == null) {
237897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NullPointerException("name == null");
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((tag < 0) || (tag > 8)) {
240897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("GeneralName: unknown tag: " + tag);
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = tag;
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name_encoding = new byte[name.length];
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.arraycopy(name, 0, this.name_encoding, 0, name.length);
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = nameASN1[tag].decode(this.name_encoding);
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
247f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the tag of the name in the structure
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getTag() {
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return tag;
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
256f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @return the value of the name.
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The class of name object depends on the tag as follows:
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [0] otherName - OtherName object,
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [1] rfc822Name - String object,
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [2] dNSName - String object,
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [3] x400Address - ORAddress object,
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [4] directoryName - instance of Name object,
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [5] ediPartyName - EDIPartyName object,
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [6] uniformResourceIdentifier - String object,
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [7] iPAddress - array of bytes such as:
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  For IP v4, as specified in RFC 791, the address must
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  contain exactly 4 byte component.  For IP v6, as specified in
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  RFC 1883, the address must contain exactly 16 byte component.
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  If GeneralName structure is used as a part of Name Constraints
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  extension, to represent an address range the number of address
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  component is doubled (to 8 and 32 bytes respectively).
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [8] registeredID - String.
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Object getName() {
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name;
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
277f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
2785c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson    public boolean equals(Object other) {
2795c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson        if (!(other instanceof GeneralName)) {
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
2825c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson        GeneralName gname = (GeneralName) other;
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (this.tag != gname.tag) {
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch(tag) {
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return ((String) name).equalsIgnoreCase(
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        (String) gname.getName());
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals((int[]) name, (int[]) gname.name);
294f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case IP_ADDR:
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // iPAddress [7], check by using ranges.
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals((byte[]) name, (byte[]) gname.name);
297f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case DIR_NAME:
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals(getEncoded(), gname.getEncoded());
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
307f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
3089efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes    public int hashCode() {
3099efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        switch (tag) {
3109efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case RFC822_NAME:
3119efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case DNS_NAME:
3129efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case UR_ID:
3139efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case REG_ID:
3149efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case IP_ADDR:
3159efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes            return name.hashCode();
3169efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case DIR_NAME:
3179efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case X400_ADDR:
3189efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case OTHER_NAME:
3199efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case EDIP_NAME:
320196f44e24830d0e7fd17eba627704a162eba779eElliott Hughes            return Arrays.hashCode(getEncoded());
3219efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        default:
3229efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes            return super.hashCode();
3239efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        }
3249efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes    }
325f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks if the other general name is acceptable by this object.
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The name is acceptable if it has the same type name and its
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * name value is equal to name value of this object. Also the name
330f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * is acceptable if this general name object is a part of name
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * constraints and the specified name is satisfied the restriction
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provided by this object (for more detail see section 4.2.1.11
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of rfc 3280).
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Note that for X400Address [3] check procedure is unclear so method
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * just checks the equality of encoded forms.
336f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * For otherName [0], ediPartyName [5], and registeredID [8]
337f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * the check procedure if not defined by rfc 3280 and for names of
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * these types this method also checks only for equality of encoded forms.
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isAcceptable(GeneralName gname) {
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (this.tag != gname.getTag()) {
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (this.tag) {
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
346f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // Mail address [1]:
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // a@b.c - particular address is acceptable by the same address,
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // or by b.c - host name.
349fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                return ((String) gname.getName()).toLowerCase(Locale.US)
350fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                    .endsWith(((String) name).toLowerCase(Locale.US));
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
352f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // DNS name [2] that can be constructed by simply adding
353f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // to the left hand side of the name satisfies the name
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // constraint: aaa.aa.aa satisfies to aaa.aa.aa, aa.aa, ..
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String dns = (String) name;
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String _dns = (String) gname.getName();
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (dns.equalsIgnoreCase(_dns)) {
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return true;
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
360fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                    return _dns.toLowerCase(Locale.US).endsWith("." + dns.toLowerCase(Locale.US));
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
363f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // For URIs the constraint ".xyz.com" is satisfied by both
364f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // abc.xyz.com and abc.def.xyz.com.  However, the constraint
365f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // ".xyz.com" is not satisfied by "xyz.com".
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // When the constraint does not begin with a period, it
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // specifies a host.
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Extract the host from URI:
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String uri = (String) name;
370f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                int begin = uri.indexOf("://")+3;
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int end = uri.indexOf('/', begin);
372f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                String host = (end == -1)
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                ? uri.substring(begin)
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : uri.substring(begin, end);
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                uri = (String) gname.getName();
376f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                begin = uri.indexOf("://")+3;
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                end = uri.indexOf('/', begin);
378f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                String _host = (end == -1)
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                ? uri.substring(begin)
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : uri.substring(begin, end);
381f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                if (host.startsWith(".")) {
382fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                    return _host.toLowerCase(Locale.US).endsWith(host.toLowerCase(Locale.US));
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return host.equalsIgnoreCase(_host);
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
386f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case IP_ADDR:
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // iPAddress [7], check by using ranges.
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                byte[] address = (byte[]) name;
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                byte[] _address = (byte[]) gname.getName();
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int length = address.length;
3913b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root
3923b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                /*
3933b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 * For IP v4, as specified in RFC 791, the address must contain
3943b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 * exactly 4 byte component. For IP v6, as specified in RFC
3953b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 * 1883, the address must contain exactly 16 byte component. If
3963b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 * GeneralName structure is used as a part of Name Constraints
3973b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 * extension, to represent an address range the number of
3983b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 * address component is doubled (to 8 and 32 bytes
3993b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 * respectively).
4003b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                 */
4013b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                if (length != 4 && length != 8 && length != 16 && length != 32) {
4023b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                    return false;
4033b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root                }
4043b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int _length = _address.length;
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (length == _length) {
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return Arrays.equals(address, _address);
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (length == 2*_length) {
409fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                    for (int i = 0; i < _address.length; i++) {
4106ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson                        // TODO: should the 2nd IP address be treated as a range or as a mask?
4116ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson                        int octet = _address[i] & 0xff;
4126ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson                        int min = address[i] & 0xff;
4136ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson                        int max = address[i + _length] & 0xff;
4146ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson                        if ((octet < min) || (octet > max)) {
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            return false;
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return true;
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return false;
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
422f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case DIR_NAME:
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // FIXME: false:
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // directoryName according to 4.1.2.4
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // comparing the encoded forms of the names
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                //TODO:
427f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                //Legacy implementations exist where an RFC 822 name
428f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                //is embedded in the subject distinguished name in an
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                //attribute of type EmailAddress
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals(getEncoded(), gname.getEncoded());
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return true;
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
440f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets a list representation of this GeneralName object.
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The first entry of the list is an Integer object representing
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the type of mane (0-8), and the second entry is a value of the name:
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * string or ASN.1 DER encoded form depending on the type as follows:
446f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * rfc822Name, dNSName, uniformResourceIdentifier names are returned
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * as Strings, using the string formats for those types (rfc 3280)
448f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * IP v4 address names are returned using dotted quad notation.
449f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * IP v6 address names are returned in the form "p1:p2:...:p8",
450f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * where p1-p8 are hexadecimal values representing the eight 16-bit
451f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * pieces of the address. registeredID name are returned as Strings
452f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * represented as a series of nonnegative integers separated by periods.
453f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * And directory names (distinguished names) are returned in
454f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * RFC 2253 string format.
455f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * otherName, X400Address, ediPartyName returned as byte arrays
456f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * containing the ASN.1 DER encoded form of the name.
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
4585c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson    public List<Object> getAsList() {
4595c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson        ArrayList<Object> result = new ArrayList<Object>();
460fb0ec0e650bf8be35acb0d47da0311a7c446aa33Elliott Hughes        result.add(tag);
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (tag) {
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((OtherName) name).getEncoded());
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(name); // String
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(ObjectIdentifier.toString((int[]) name));
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((ORAddress) name).getEncoded());
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DIR_NAME: // directoryName is returned as a String
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((Name) name).getName(X500Principal.RFC2253));
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((EDIPartyName) name).getEncoded());
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case IP_ADDR: //iPAddress is returned as a String, not as a byte array
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(ipBytesToStr((byte[]) name));
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return Collections.unmodifiableList(result);
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
492f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        String result = "";
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (tag) {
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
495f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "otherName[0]: "
4964b25199bc0b7a64a6feaa60e7d5d6b0474341234Elliott Hughes                         + Array.getBytesAsString(getEncoded());
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
499f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "rfc822Name[1]: " + name;
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
502f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "dNSName[2]: " + name;
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
505f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "uniformResourceIdentifier[6]: " + name;
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
508f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "registeredID[8]: " + ObjectIdentifier.toString((int[]) name);
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
511f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "x400Address[3]: "
5124b25199bc0b7a64a6feaa60e7d5d6b0474341234Elliott Hughes                         + Array.getBytesAsString(getEncoded());
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
514f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case DIR_NAME:
515f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "directoryName[4]: "
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         + ((Name) name).getName(X500Principal.RFC2253);
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
519f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "ediPartyName[5]: "
5204b25199bc0b7a64a6feaa60e7d5d6b0474341234Elliott Hughes                         + Array.getBytesAsString(getEncoded());
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
522f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case IP_ADDR:
523f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "iPAddress[7]: " + ipBytesToStr((byte[]) name);
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
528adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
530f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns ASN.1 encoded form of this X.509 GeneralName value.
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
534adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public byte[] getEncoded() {
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (encoding == null) {
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            encoding = ASN1.encode(this);
537adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return encoding;
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
542f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @return the encoded value of the name without the tag associated
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         with the name in the GeneralName structure
544f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @throws  IOException
545adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public byte[] getEncodedName() {
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name_encoding == null) {
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            name_encoding = nameASN1[tag].encode(name);
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name_encoding;
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
5548626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson     * Checks the correctness of the string representation of DNS name as
5558626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson     * specified in RFC 1034 p. 10 and RFC 1123 section 2.1.
5568626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson     *
5578626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson     * <p>This permits a wildcard character '*' anywhere in the name; it is up
5588626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson     * to the application to check which wildcards are permitted. See RFC 6125
5598626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson     * for recommended wildcard matching rules.
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static void checkDNS(String dns) throws IOException {
562fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        String string = dns.toLowerCase(Locale.US);
563fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        int length = string.length();
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // indicates if it is a first letter of the label
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean first_letter = true;
566fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        for (int i = 0; i < length; i++) {
567fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom            char ch = string.charAt(i);
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (first_letter) {
5698626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson                if ((ch > 'z' || ch < 'a') && (ch < '0' || ch > '9') && (ch != '*')) {
570897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw new IOException("DNS name must start with a letter: " + dns);
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                first_letter = false;
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')
5768626012f833cada8b06c3d82860d2dbe4107ce7aJesse Wilson                    || (ch == '-') || (ch == '.') || (ch == '*'))) {
577897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Incorrect DNS name: " + dns);
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (ch == '.') {
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check the end of the previous label, it should not
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // be '-' sign
582fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                if (string.charAt(i-1) == '-') {
583897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw new IOException("Incorrect DNS name: label ends with '-': " + dns);
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                first_letter = true;
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks the correctness of the string representation of URI name.
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The correctness is checked as pointed out in RFC 3280 p. 34.
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static void checkURI(String uri) throws IOException {
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            URI ur = new URI(uri);
597897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            if (ur.getScheme() == null || ur.getRawSchemeSpecificPart().isEmpty()) {
598897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("No scheme or scheme-specific-part in uniformResourceIdentifier: " + uri);
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!ur.isAbsolute()) {
601897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Relative uniformResourceIdentifier: " + uri);
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (URISyntaxException e) {
604897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw (IOException) new IOException("Bad representation of uniformResourceIdentifier: " + uri).initCause(e);
605f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
610fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom     * Converts OID into array of ints.
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static int[] oidStrToInts(String oid) throws IOException {
613fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        int length = oid.length();
614fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        if (oid.charAt(length-1) == '.') {
615897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("Bad OID: " + oid);
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
617fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        int[] result = new int[length/2+1]; // best case: a.b.c.d.e
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int number = 0; // the number of OID's components
619fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        for (int i = 0; i < length; i++) {
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int value = 0;
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int pos = i;
622fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom            for (; i < length; i++) {
623fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                char ch = oid.charAt(i);
624fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                if ((ch < '0') || (ch > '9')) {
625fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                    break;
626fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                }
627fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom                value = 10 * value + (ch - '0');
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (i == pos) {
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // the number was not read
631897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Bad OID: " + oid);
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result[number++] = value;
634fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom            if (i == length) {
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
637fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom            char ch = oid.charAt(i);
638fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom            if (ch != '.') {
639897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Bad OID: " + oid);
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (number < 2) {
643897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("OID should consist of no less than 2 components: " + oid);
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
645fe921473907c2388cf13d014dd3bcf32d2b6d04aBrian Carlstrom        return Arrays.copyOfRange(result, 0, number);
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
6496ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson     * Returns the bytes of the given IP address or masked IP address.
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static byte[] ipStrToBytes(String ip) throws IOException {
6526ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson        if (!InetAddress.isNumeric(ip)) {
6536ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson            throw new IOException("Not an IP address: " + ip);
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
6556ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson        return InetAddress.getByName(ip).getAddress();
656897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes    }
657f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
6593b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root     * Returns the string form of the given IP address. If the address is not 4
6603b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root     * octets for IPv4 or 16 octets for IPv6, an IllegalArgumentException will
6613b14c4bd5c7ce28ed3485bd24285c58424c074afKenny Root     * be thrown.
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static String ipBytesToStr(byte[] ip) {
6646ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson        try {
6656ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson            return InetAddress.getByAddress(null, ip).getHostAddress();
6666ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson        } catch (UnknownHostException e) {
6676ed93fa8be996378e766d3fd2586b51c6fe656b1Jesse Wilson            throw new IllegalArgumentException("Unexpected IP address: " + Arrays.toString(ip));
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
670f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
67128d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root    /**
67228d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root     * The "Name" is actually a CHOICE of one entry, so we need to pretend it's
67328d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root     * a SEQUENCE OF and just grab the first entry.
67428d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root     */
67528d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root    private static final ASN1SequenceOf NAME_ASN1 = new ASN1SequenceOf(Name.ASN1) {
67628d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root        @Override
67728d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root        public Object decode(BerInputStream in) throws IOException {
67828d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root            return ((List<?>) super.decode(in)).get(0);
67928d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root        }
68028d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root    };
68128d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final ASN1Choice ASN1 = new ASN1Choice(new ASN1Type[] {
683f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes           new ASN1Implicit(0, OtherName.ASN1),
684f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes           new ASN1Implicit(1, ASN1StringType.IA5STRING),
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(2, ASN1StringType.IA5STRING),
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(3, ORAddress.ASN1),
68728d504c4188a5d25a7209e4d1c131e0afffa1fcfKenny Root           new ASN1Implicit(4, NAME_ASN1),
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(5, EDIPartyName.ASN1),
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(6, ASN1StringType.IA5STRING),
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(7, ASN1OctetString.getInstance()),
691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(8, ASN1Oid.getInstance()) }) {
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public Object getObjectToEncode(Object value) {
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return ((GeneralName) value).name;
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
696f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int getIndex(java.lang.Object object) {
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return  ((GeneralName) object).tag;
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
7015c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson        @Override public Object getDecodedObject(BerInputStream in) throws IOException {
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            GeneralName result;
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            switch (in.choiceIndex) {
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case OTHER_NAME: // OtherName
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((OtherName) in.content);
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case RFC822_NAME: // rfc822Name
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case DNS_NAME: // dNSName
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName(in.choiceIndex, (String) in.content);
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case X400_ADDR:
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((ORAddress) in.content);
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case DIR_NAME: // directoryName (X.500 Name)
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((Name) in.content);
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case EDIP_NAME: // ediPartyName
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((EDIPartyName) in.content);
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case UR_ID: // uniformResourceIdentifier
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    String uri = (String) in.content;
722f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    if (uri.indexOf(":") == -1) {
723897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                        throw new IOException("GeneralName: scheme is missing in URI: " + uri);
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName(in.choiceIndex, uri);
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case IP_ADDR: // iPAddress
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((byte[]) in.content);
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case REG_ID: // registeredID
731f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    result = new GeneralName(in.choiceIndex,
732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            ObjectIdentifier.toString((int[]) in.content));
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                default:
735897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw new IOException("GeneralName: unknown tag: " + in.choiceIndex);
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result.encoding = in.getEncoded();
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return result;
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    };
741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
742