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