GeneralName.java revision fb0ec0e650bf8be35acb0d47da0311a7c446aa33
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;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URI;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.URISyntaxException;
28e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughesimport java.nio.charset.Charsets;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Collections;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.security.auth.x500.X500Principal;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Choice;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Implicit;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1OctetString;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Oid;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1StringType;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Type;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.BerInputStream;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ObjectIdentifier;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.x501.Name;
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
45f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * The class encapsulates the ASN.1 DER encoding/decoding work
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * with the GeneralName structure which is a part of X.509 certificate
47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (as specified in RFC 3280 -
48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Internet X.509 Public Key Infrastructure.
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Certificate and Certificate Revocation List (CRL) Profile.
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  http://www.ietf.org/rfc/rfc3280.txt):
51f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre>
53f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   GeneralName::= CHOICE {
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        otherName                       [0]     OtherName,
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        rfc822Name                      [1]     IA5String,
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        dNSName                         [2]     IA5String,
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        x400Address                     [3]     ORAddress,
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        directoryName                   [4]     Name,
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        ediPartyName                    [5]     EDIPartyName,
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        uniformResourceIdentifier       [6]     IA5String,
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        iPAddress                       [7]     OCTET STRING,
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        registeredID                    [8]     OBJECT IDENTIFIER
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
65f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   OtherName::= SEQUENCE {
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        type-id    OBJECT IDENTIFIER,
68f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *        value      [0] EXPLICIT ANY DEFINED BY type-id
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
70f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   EDIPartyName::= SEQUENCE {
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        nameAssigner            [0]     DirectoryString OPTIONAL,
73f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *        partyName               [1]     DirectoryString
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
75f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   DirectoryString::= CHOICE {
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        teletexString             TeletexString   (SIZE (1..MAX)),
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        printableString           PrintableString (SIZE (1..MAX)),
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        universalString           UniversalString (SIZE (1..MAX)),
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *        utf8String              UTF8String      (SIZE (1..MAX)),
81f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *        bmpString               BMPString       (SIZE (1..MAX))
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *   }
83f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre>
85f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see org.apache.harmony.security.x509.NameConstraints
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see org.apache.harmony.security.x509.GeneralSubtree
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class GeneralName {
90f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The values of the tags of fields
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int OTHER_NAME = 0;
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int RFC822_NAME = 1;
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int DNS_NAME = 2;
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int X400_ADDR = 3;
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int DIR_NAME = 4;
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int EDIP_NAME = 5;
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int UR_ID = 6;
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int IP_ADDR = 7;
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final int REG_ID = 8;
103f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // ASN1 encoders/decoders for name choices
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static ASN1Type[] nameASN1 = new ASN1Type[9];
106f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static {
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[OTHER_NAME] = OtherName.ASN1;
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[RFC822_NAME] = ASN1StringType.IA5STRING;
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[DNS_NAME] = ASN1StringType.IA5STRING;
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[UR_ID] = ASN1StringType.IA5STRING;
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[X400_ADDR] = ORAddress.ASN1;
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[DIR_NAME] = Name.ASN1;
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[EDIP_NAME] = EDIPartyName.ASN1;
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[IP_ADDR] = ASN1OctetString.getInstance();
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        nameASN1[REG_ID] = ASN1Oid.getInstance();
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
118f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // the tag of the name type
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int tag;
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // the name value (can be String or byte array)
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Object name;
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // the ASN.1 encoded form of GeneralName
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private byte[] encoding;
125f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    // the ASN.1 encoded form of GeneralName's field
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private byte[] name_encoding;
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Makes the GeneralName object from the tag type and corresponding
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * well established string representation of the name value.
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The String representation of [7] iPAddress is such as:
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  For IP v4, as specified in RFC 791, the address must
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  contain exactly 4 byte component.  For IP v6, as specified in
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  RFC 1883, the address must contain exactly 16 byte component.
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  If GeneralName structure is used as a part of Name Constraints
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  extension, to represent an address range the number of address
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  component is doubled (to 8 and 32 bytes respectively).
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Note that the names:
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [0] otherName, [3] x400Address, [5] ediPartyName
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *   have no the string representation, so exception will be thrown.
141f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * To make the GeneralName object with such names use another constructor.
142f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @param tag is an integer which value corresponds to the name type.
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name is a name value corresponding to the tag.
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * <pre>
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(int tag, String name) throws IOException {
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name == null) {
148897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("name == null");
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = tag;
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (tag) {
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME :
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR :
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME :
155897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Unknown string representation for type [" + tag + "]");
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME :
157f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // according to RFC 3280 p.34 the DNS name should be
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // checked against the
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // RFC 1034 p.10 (3.5. Preferred name syntax):
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                checkDNS(name);
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = name;
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID :
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check the uniformResourceIdentifier for correctness
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // according to RFC 3280 p.34
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                checkURI(name);
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = name;
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME :
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = name;
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = oidStrToInts(name);
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DIR_NAME :
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = new Name(name);
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case IP_ADDR :
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                this.name = ipStrToBytes(name);
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
182897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Unknown type: [" + tag + "]");
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TODO
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param   name:   OtherName
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(OtherName name) {
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = OTHER_NAME;
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TODO
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param   name:   ORAddress
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    /**
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TODO
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param   name:   Name
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(Name name) {
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = DIR_NAME;
210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TODO
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param   name:   EDIPartyName
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(EDIPartyName name) {
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = EDIP_NAME;
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = name;
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
222f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Constructor for type [7] iPAddress.
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * name is an array of bytes such as:
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  For IP v4, as specified in RFC 791, the address must
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  contain exactly 4 byte component.  For IP v6, as specified in
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  RFC 1883, the address must contain exactly 16 byte component.
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  If GeneralName structure is used as a part of Name Constraints
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  extension, to represent an address range the number of address
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  component is doubled (to 8 and 32 bytes respectively).
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public GeneralName(byte[] name) throws IllegalArgumentException {
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int length = name.length;
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (length != 4 && length != 8 && length != 16 && length != 32) {
234897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IllegalArgumentException("name.length invalid");
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = IP_ADDR;
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = new byte[name.length];
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.arraycopy(name, 0, this.name, 0, name.length);
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructs an object representing the value of GeneralName.
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param tag is an integer which value corresponds
244f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * to the name type (0-8),
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param name is a DER encoded for of the name value
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
247897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes    public GeneralName(int tag, byte[] name) throws IOException {
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name == null) {
249897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new NullPointerException("name == null");
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if ((tag < 0) || (tag > 8)) {
252897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("GeneralName: unknown tag: " + tag);
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.tag = tag;
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name_encoding = new byte[name.length];
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        System.arraycopy(name, 0, this.name_encoding, 0, name.length);
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.name = nameASN1[tag].decode(this.name_encoding);
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
259f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns the tag of the name in the structure
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the tag of the name
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public int getTag() {
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return tag;
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
269f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @return the value of the name.
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The class of name object depends on the tag as follows:
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [0] otherName - OtherName object,
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [1] rfc822Name - String object,
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [2] dNSName - String object,
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [3] x400Address - ORAddress object,
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [4] directoryName - instance of Name object,
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [5] ediPartyName - EDIPartyName object,
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [6] uniformResourceIdentifier - String object,
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [7] iPAddress - array of bytes such as:
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  For IP v4, as specified in RFC 791, the address must
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  contain exactly 4 byte component.  For IP v6, as specified in
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  RFC 1883, the address must contain exactly 16 byte component.
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  If GeneralName structure is used as a part of Name Constraints
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  extension, to represent an address range the number of address
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  component is doubled (to 8 and 32 bytes respectively).
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * [8] registeredID - String.
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public Object getName() {
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name;
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
290f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TODO
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param   _gname: Object
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean equals(Object _gname) {
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!(_gname instanceof GeneralName)) {
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        GeneralName gname = (GeneralName) _gname;
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (this.tag != gname.tag) {
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch(tag) {
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return ((String) name).equalsIgnoreCase(
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        (String) gname.getName());
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals((int[]) name, (int[]) gname.name);
312f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case IP_ADDR:
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // iPAddress [7], check by using ranges.
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals((byte[]) name, (byte[]) gname.name);
315f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case DIR_NAME:
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals(getEncoded(), gname.getEncoded());
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //System.out.println(false);
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return false;
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
326f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
3279efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes    public int hashCode() {
3289efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        switch (tag) {
3299efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case RFC822_NAME:
3309efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case DNS_NAME:
3319efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case UR_ID:
3329efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case REG_ID:
3339efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case IP_ADDR:
3349efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes            return name.hashCode();
3359efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case DIR_NAME:
3369efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case X400_ADDR:
3379efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case OTHER_NAME:
3389efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        case EDIP_NAME:
3399efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes            return getEncoded().hashCode();
3409efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        default:
3419efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes            return super.hashCode();
3429efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes        }
3439efa300c26865520498c0ed132ff9ebe499e7d84Elliott Hughes    }
344f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks if the other general name is acceptable by this object.
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The name is acceptable if it has the same type name and its
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * name value is equal to name value of this object. Also the name
349f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * is acceptable if this general name object is a part of name
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * constraints and the specified name is satisfied the restriction
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * provided by this object (for more detail see section 4.2.1.11
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * of rfc 3280).
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Note that for X400Address [3] check procedure is unclear so method
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * just checks the equality of encoded forms.
355f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * For otherName [0], ediPartyName [5], and registeredID [8]
356f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * the check procedure if not defined by rfc 3280 and for names of
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * these types this method also checks only for equality of encoded forms.
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean isAcceptable(GeneralName gname) {
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (this.tag != gname.getTag()) {
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return false;
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (this.tag) {
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
365f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // Mail address [1]:
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // a@b.c - particular address is acceptable by the same address,
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // or by b.c - host name.
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return ((String) gname.getName()).toLowerCase()
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    .endsWith(((String) name).toLowerCase());
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
371f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // DNS name [2] that can be constructed by simply adding
372f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // to the left hand side of the name satisfies the name
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // constraint: aaa.aa.aa satisfies to aaa.aa.aa, aa.aa, ..
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String dns = (String) name;
375adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String _dns = (String) gname.getName();
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (dns.equalsIgnoreCase(_dns)) {
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return true;
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
379f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    return _dns.toLowerCase().endsWith("." + dns.toLowerCase());
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
382f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // For URIs the constraint ".xyz.com" is satisfied by both
383f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // abc.xyz.com and abc.def.xyz.com.  However, the constraint
384f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                // ".xyz.com" is not satisfied by "xyz.com".
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // When the constraint does not begin with a period, it
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // specifies a host.
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // Extract the host from URI:
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                String uri = (String) name;
389f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                int begin = uri.indexOf("://")+3;
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int end = uri.indexOf('/', begin);
391f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                String host = (end == -1)
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                ? uri.substring(begin)
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : uri.substring(begin, end);
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                uri = (String) gname.getName();
395f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                begin = uri.indexOf("://")+3;
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                end = uri.indexOf('/', begin);
397f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                String _host = (end == -1)
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                ? uri.substring(begin)
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                : uri.substring(begin, end);
400f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                if (host.startsWith(".")) {
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return _host.toLowerCase().endsWith(host.toLowerCase());
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return host.equalsIgnoreCase(_host);
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
405f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case IP_ADDR:
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // iPAddress [7], check by using ranges.
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                byte[] address = (byte[]) name;
408adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                byte[] _address = (byte[]) gname.getName();
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int length = address.length;
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int _length = _address.length;
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (length == _length) {
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return Arrays.equals(address, _address);
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (length == 2*_length) {
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    for (int i=0; i<_address.length; i++) {
415f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                        if ((_address[i] < address[i])
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                || (_address[i] > address[i+_length])) {
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            return false;
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
419adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return true;
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return false;
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
424f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case DIR_NAME:
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // FIXME: false:
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // directoryName according to 4.1.2.4
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // comparing the encoded forms of the names
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                //TODO:
429f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                //Legacy implementations exist where an RFC 822 name
430f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                //is embedded in the subject distinguished name in an
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                //attribute of type EmailAddress
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
434adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return Arrays.equals(getEncoded(), gname.getEncoded());
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return true;
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
442f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
443adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
444adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets a list representation of this GeneralName object.
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The first entry of the list is an Integer object representing
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * the type of mane (0-8), and the second entry is a value of the name:
447adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * string or ASN.1 DER encoded form depending on the type as follows:
448f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * rfc822Name, dNSName, uniformResourceIdentifier names are returned
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * as Strings, using the string formats for those types (rfc 3280)
450f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * IP v4 address names are returned using dotted quad notation.
451f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * IP v6 address names are returned in the form "p1:p2:...:p8",
452f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * where p1-p8 are hexadecimal values representing the eight 16-bit
453f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * pieces of the address. registeredID name are returned as Strings
454f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * represented as a series of nonnegative integers separated by periods.
455f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * And directory names (distinguished names) are returned in
456f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * RFC 2253 string format.
457f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * otherName, X400Address, ediPartyName returned as byte arrays
458f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * containing the ASN.1 DER encoded form of the name.
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public List getAsList() {
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ArrayList result = new ArrayList();
462fb0ec0e650bf8be35acb0d47da0311a7c446aa33Elliott Hughes        result.add(tag);
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (tag) {
464adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((OtherName) name).getEncoded());
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(name); // String
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(ObjectIdentifier.toString((int[]) name));
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((ORAddress) name).getEncoded());
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DIR_NAME: // directoryName is returned as a String
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((Name) name).getName(X500Principal.RFC2253));
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(((EDIPartyName) name).getEncoded());
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case IP_ADDR: //iPAddress is returned as a String, not as a byte array
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result.add(ipBytesToStr((byte[]) name));
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return Collections.unmodifiableList(result);
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
493f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // TODO
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // @param   data:   byte[]
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // @return
497f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private String getBytesAsString(byte[] data) {
499f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        String result = "";
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i=0; i<data.length; i++) {
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String tail = Integer.toHexString(0x00ff & data[i]);
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (tail.length() == 1) {
503f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                tail = "0" + tail;
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
505f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            result += tail + " ";
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
511adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * TODO
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String toString() {
515f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        String result = "";
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        switch (tag) {
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case OTHER_NAME:
518f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "otherName[0]: "
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         + getBytesAsString(getEncoded());
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case RFC822_NAME:
522f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "rfc822Name[1]: " + name;
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case DNS_NAME:
525f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "dNSName[2]: " + name;
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
527adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case UR_ID:
528f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "uniformResourceIdentifier[6]: " + name;
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case REG_ID:
531f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "registeredID[8]: " + ObjectIdentifier.toString((int[]) name);
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case X400_ADDR:
534f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "x400Address[3]: "
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         + getBytesAsString(getEncoded());
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
537f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case DIR_NAME:
538f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "directoryName[4]: "
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         + ((Name) name).getName(X500Principal.RFC2253);
540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            case EDIP_NAME:
542f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "ediPartyName[5]: "
543adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         + getBytesAsString(getEncoded());
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
545f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes            case IP_ADDR:
546f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                result = "iPAddress[7]: " + ipBytesToStr((byte[]) name);
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            default:
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // should never happen
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
553f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns ASN.1 encoded form of this X.509 GeneralName value.
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return a byte array containing ASN.1 encode form.
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public byte[] getEncoded() {
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (encoding == null) {
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            encoding = ASN1.encode(this);
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return encoding;
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
566f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @return the encoded value of the name without the tag associated
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         with the name in the GeneralName structure
568f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * @throws  IOException
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public byte[] getEncodedName() {
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (name_encoding == null) {
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            name_encoding = nameASN1[tag].encode(name);
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return name_encoding;
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks the correctness of the string representation of DNS name.
5792f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     * The correctness is checked as specified in RFC 1034 p. 10, and modified
5802f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes     * by RFC 1123 (section 2.1).
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static void checkDNS(String dns) throws IOException {
583e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughes        byte[] bytes = dns.toLowerCase().getBytes(Charsets.UTF_8);
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // indicates if it is a first letter of the label
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean first_letter = true;
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i=0; i<bytes.length; i++) {
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            byte ch = bytes[i];
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (first_letter) {
5892f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                if ((bytes.length > 2) && (ch == '*') && (bytes[1] == '.')) {
5902f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                    first_letter = false;
5912f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                    continue;
5922f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                }
5932f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                if ((ch > 'z' || ch < 'a') && (ch < '0' || ch > '9')) {
594897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw new IOException("DNS name must start with a letter: " + dns);
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                first_letter = false;
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!((ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9')
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    || (ch == '-') || (ch == '.'))) {
601897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Incorrect DNS name: " + dns);
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (ch == '.') {
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check the end of the previous label, it should not
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // be '-' sign
6062f9e468ed4985edfd5e351faf2089d91e561e41dElliott Hughes                if (bytes[i-1] == '-') {
607897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw new IOException("Incorrect DNS name: label ends with '-': " + dns);
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                first_letter = true;
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Checks the correctness of the string representation of URI name.
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The correctness is checked as pointed out in RFC 3280 p. 34.
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static void checkURI(String uri) throws IOException {
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            URI ur = new URI(uri);
621897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            if (ur.getScheme() == null || ur.getRawSchemeSpecificPart().isEmpty()) {
622897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("No scheme or scheme-specific-part in uniformResourceIdentifier: " + uri);
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!ur.isAbsolute()) {
625897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Relative uniformResourceIdentifier: " + uri);
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (URISyntaxException e) {
628897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw (IOException) new IOException("Bad representation of uniformResourceIdentifier: " + uri).initCause(e);
629f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Converts OID into array of bytes.
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static int[] oidStrToInts(String oid) throws IOException {
637e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughes        byte[] bytes = oid.getBytes(Charsets.UTF_8);
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (bytes[bytes.length-1] == '.') {
639897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("Bad OID: " + oid);
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int[] result = new int[bytes.length/2+1]; // best case: a.b.c.d.e
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int number = 0; // the number of OID's components
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i=0; i<bytes.length; i++) {
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int value = 0;
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int pos = i;
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while ((i < bytes.length) && (bytes[i] >= '0')
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && (bytes[i] <= '9')) {
648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                value = 10 * value + (bytes[i++] - 48);
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (i == pos) {
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // the number was not read
652897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Bad OID: " + oid);
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result[number++] = value;
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (i >= bytes.length) {
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break;
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (bytes[i] != '.') {
659897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("Bad OID: " + oid);
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (number < 2) {
663897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes            throw new IOException("OID should consist of no less than 2 components: " + oid);
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int[] res = new int[number];
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        for (int i=0; i<number; i++) {
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            res[i] = result[i];
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return res;
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Helper method. Converts the String representation of IP address
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to the array of bytes. IP addresses are expected in two versions:<br>
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * IPv4 - in dot-decimal notation<br>
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * IPv6 - in colon hexadecimal notation<br>
677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Also method works with the ranges of the addresses represented
678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * as 2 addresses separated by '/' character.
679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param   address :   String representation of IP address
680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return  byte representation of IP address
681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static byte[] ipStrToBytes(String ip) throws IOException {
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean isIPv4 = (ip.indexOf('.') > 0);
684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // number of components (should be 4 or 8)
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int num_components = (isIPv4) ? 4 : 16;
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (ip.indexOf('/') > 0) {
687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            num_components *= 2; // this is a range of addresses
688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // the resulting array
690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] result = new byte[num_components];
691e810d3b49631329b11440aa5b7a54db181d42ed1Elliott Hughes        byte[] ip_bytes = ip.getBytes(Charsets.UTF_8);
692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // number of address component to be read
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int component = 0;
694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // if it is reading the second bound of a range
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean reading_second_bound = false;
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isIPv4) {
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // IPv4 address is expected in the form of dot-decimal notation:
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //      1.100.2.200
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // or in the range form:
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            //      1.100.2.200/1.100.3.300
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int i = 0;
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            while (i < ip_bytes.length) {
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int digits = 0;
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // the value of the address component
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                int value = 0;
706897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                while ((i < ip_bytes.length) && (ip_bytes[i] >= '0') && (ip_bytes[i] <= '9')) {
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    digits++;
708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (digits > 3) {
709897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                        throw new IOException("Component of IPv4 address should consist of no more than 3 decimal digits: " + ip);
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = 10 * value + (ip_bytes[i] - 48);
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    i++;
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (digits == 0) {
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // ip_bytes[i] is not a number
716897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw badIp(4, ip);
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result[component] = (byte) value;
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                component++;
720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (i >= ip_bytes.length) {
721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // no more bytes
722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check the reached delimiter
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if ((ip_bytes[i] != '.' && ip_bytes[i] != '/')) {
726897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw badIp(4, ip);
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check the correctness of the range
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (ip_bytes[i] == '/') {
730adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (reading_second_bound) {
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // more than 2 bounds in the range
732897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                        throw badIp(4, ip);
733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (component != 4) {
735897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                        throw new IOException("IPv4 address should consist of 4 decimal numbers: " + ip);
736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    reading_second_bound = true;
738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // check the number of the components
740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (component > ((reading_second_bound) ? 7 : 3)) {
741897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw new IOException("IPv4 address should consist of 4 decimal numbers: " + ip);
742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                i++;
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // check the number of read components
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (component != num_components) {
747897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw new IOException("IPv4 address should consist of 4 decimal numbers: " + ip);
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // IPv6 address is expected in the form of
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // colon hexadecimal notation:
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // 010a:020b:3337:1000:FFFA:ABCD:9999:0000
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // or in a range form:
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // 010a:020b:3337:1000:FFFA:ABCD:9999:0000/010a:020b:3337:1000:FFFA:ABCD:9999:1111
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (ip_bytes.length != 39 && ip_bytes.length != 79) {
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // incorrect length of the string representation
757897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw badIp(6, ip);
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int value = 0;
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // indicates the reading of the second half of byte
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean second_hex = false;
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // if the delimiter (':' or '/') is expected
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean expect_delimiter = false;
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i=0; i<ip_bytes.length; i++) {
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                byte bytik = ip_bytes[i];
766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if ((bytik >= '0') && (bytik <= '9')) {
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = (bytik - 48); // '0':0, '1':1, ... , '9':9
768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if ((bytik >= 'A') && (bytik <= 'F')) {
769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = (bytik - 55); // 'A':10, 'B':11, ... , 'F':15
770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if ((bytik >= 'a') && (bytik <= 'f')) {
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    value = (bytik - 87); // 'a':10, 'b':11, ... , 'f':15
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if (second_hex) {
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // second hex value of a byte is expected but was not read
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // (it is the situation like: ...ABCD:A:ABCD...)
775897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw badIp(6, ip);
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else if ((bytik == ':') || (bytik == '/')) {
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (component % 2 == 1) {
778f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                        // second byte of the component is omitted
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // (it is the situation like: ... ABDC:AB:ABCD ...)
780897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                        throw badIp(6, ip);
781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (bytik == '/') {
783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (reading_second_bound) {
784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // more than 2 bounds in the range
785897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                            throw badIp(6, ip);
786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (component != 16) {
788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // check the number of read components
789897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                            throw new IOException("IPv6 address should consist of 8 hexadecimal numbers: " + ip);
790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        reading_second_bound = true;
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    expect_delimiter = false;
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    continue;
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
796897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw badIp(6, ip);
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (expect_delimiter) { // delimiter is expected but was not read
799897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw badIp(6, ip);
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!second_hex) {
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // first half of byte has been read
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result[component] = (byte) (value << 4);
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    second_hex = true;
805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // second half of byte has been read
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result[component] = (byte)
808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ((result[component] & 0xFF) | value);
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // delimiter is expected if 2 bytes were read
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    expect_delimiter = (component % 2 == 1);
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    second_hex = false;
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    component++;
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // check the correctness of the read address:
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (second_hex || (component % 2 == 1)) {
817897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                throw badIp(6, ip);
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
823897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes    private static IOException badIp(int v, String ip) throws IOException {
824897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes        throw new IOException("Incorrect IPv" + v + " representation: " + ip);
825897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes    }
826f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Helper method. Converts the byte array representation of ip address
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * to the String.
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param   ip :   byte array representation of ip address
831f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *  If the length of byte array 4 then it represents an IP v4
832f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *  and the output String will be in the dotted quad form.
833f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *  If the length is 16 then it represents an IP v6
834f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *  and the output String will be returned in format "p1:p2:...:p8",
835f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *  where p1-p8 are hexadecimal values representing the eight 16-bit
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  pieces of the address.
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  If the length is 8 or 32 then it represents an address range (RFC 1519)
838adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *  and the output String will contain 2 IP address divided by "/"
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return  String representation of ip address
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static String ipBytesToStr(byte[] ip) {
842f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        String result = "";
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (ip.length < 9) { // IP v4
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i=0; i<ip.length; i++) {
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result += Integer.toString(ip[i] & 0xff);
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (i != ip.length-1) {
847f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    result += (i == 3) ? "/": ".";
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i=0; i<ip.length; i++) {
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                result += Integer.toHexString(0x00ff & ip[i]);
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if ((i % 2 != 0) && (i != ip.length-1)) {
854f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    result += (i == 15) ? "/": ":";
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return result;
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
860f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static final ASN1Choice ASN1 = new ASN1Choice(new ASN1Type[] {
862f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes           new ASN1Implicit(0, OtherName.ASN1),
863f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes           new ASN1Implicit(1, ASN1StringType.IA5STRING),
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(2, ASN1StringType.IA5STRING),
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(3, ORAddress.ASN1),
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(4, Name.ASN1),
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(5, EDIPartyName.ASN1),
868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(6, ASN1StringType.IA5STRING),
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(7, ASN1OctetString.getInstance()),
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project           new ASN1Implicit(8, ASN1Oid.getInstance()) }) {
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public Object getObjectToEncode(Object value) {
873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return ((GeneralName) value).name;
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
875f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int getIndex(java.lang.Object object) {
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return  ((GeneralName) object).tag;
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public Object getDecodedObject(BerInputStream in) throws IOException {
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            GeneralName result;
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            switch (in.choiceIndex) {
883adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case OTHER_NAME: // OtherName
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((OtherName) in.content);
885adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case RFC822_NAME: // rfc822Name
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case DNS_NAME: // dNSName
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName(in.choiceIndex, (String) in.content);
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case X400_ADDR:
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((ORAddress) in.content);
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case DIR_NAME: // directoryName (X.500 Name)
894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((Name) in.content);
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case EDIP_NAME: // ediPartyName
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((EDIPartyName) in.content);
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case UR_ID: // uniformResourceIdentifier
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    String uri = (String) in.content;
901f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    if (uri.indexOf(":") == -1) {
902897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                        throw new IOException("GeneralName: scheme is missing in URI: " + uri);
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName(in.choiceIndex, uri);
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case IP_ADDR: // iPAddress
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    result = new GeneralName((byte[]) in.content);
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case REG_ID: // registeredID
910f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    result = new GeneralName(in.choiceIndex,
911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            ObjectIdentifier.toString((int[]) in.content));
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                default:
914897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes                    throw new IOException("GeneralName: unknown tag: " + in.choiceIndex);
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            result.encoding = in.getEncoded();
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return result;
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    };
920f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // public static void printAsHex(int perLine,
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         String prefix,
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         String delimiter,
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         byte[] data) {
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     for (int i=0; i<data.length; i++) {
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         String tail = Integer.toHexString(0x000000ff & data[i]);
927adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         if (tail.length() == 1) {
928f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    //             tail = "0" + tail;
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         }
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         System.out.print(prefix + "0x" + tail + delimiter);
931f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         if (((i+1)%perLine) == 0) {
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //             System.out.println();
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //         }
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     }
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     System.out.println();
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // }
938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // public static void main(String[] args) {
940adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     System.out.println(">> "+new BigInteger(new byte[] {(byte)23, (byte)255}).toString(2));
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     System.out.println(ipBytesToStr(new byte[] {(byte)255, (byte)23, (byte)128, (byte)130}));
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     System.out.println(ipBytesToStr(new byte[] {(byte)255, (byte)23, (byte)128, (byte)130,
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130}));
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     System.out.println(ipBytesToStr(new byte[] {(byte)255, (byte)23, (byte)128, (byte)130,
945adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
946adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130}));
948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     System.out.println(ipBytesToStr(new byte[] {(byte)255, (byte)23, (byte)128, (byte)130,
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
951adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
952adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
953adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
954adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130,
955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //                                                 (byte)255, (byte)23, (byte)128, (byte)130}));
956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     ipStrToBytes("1.2.3.4");
957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     ipStrToBytes("1.2.3.4/4.3.2.1");
958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    //     printAsHex(8, "", " ", ipStrToBytes("ff17:8082:ff17:8082:ff17:8082:ff17:8082/ff17:8082:ff17:8082:ff17:8082:ff17:8082"));
959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // }
960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
961