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.security.cert.X509Certificate; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.List; 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Implicit; 30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1OctetString; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Sequence; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.ASN1Type; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.asn1.BerInputStream; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 36f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * The class encapsulates the ASN.1 DER encoding/decoding work 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * with the following structure which is a part of X.509 certificate 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (as specified in RFC 3280 - 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Internet X.509 Public Key Infrastructure. 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Certificate and Certificate Revocation List (CRL) Profile. 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.ietf.org/rfc/rfc3280.txt): 42f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <pre> 44f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * NameConstraints ::= SEQUENCE { 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * permittedSubtrees [0] GeneralSubtrees OPTIONAL, 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * excludedSubtrees [1] GeneralSubtrees OPTIONAL } 48f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree 50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * </pre> 52f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see org.apache.harmony.security.x509.GeneralSubtree 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see org.apache.harmony.security.x509.GeneralName 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 565c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilsonpublic final class NameConstraints extends ExtensionValue { 575c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** the value of permittedSubtrees field of the structure */ 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final GeneralSubtrees permittedSubtrees; 595c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** the value of excludedSubtrees field of the structure */ 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final GeneralSubtrees excludedSubtrees; 615c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** the ASN.1 encoded form of NameConstraints */ 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private byte[] encoding; 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 645c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson private ArrayList<GeneralName>[] permitted_names; 655c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson private ArrayList<GeneralName>[] excluded_names; 66f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs <code>NameConstrains</code> object 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 70f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes public NameConstraints(GeneralSubtrees permittedSubtrees, 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project GeneralSubtrees excludedSubtrees) { 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (permittedSubtrees != null) { 735c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson List<GeneralSubtree> ps = permittedSubtrees.getSubtrees(); 745c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson if (ps == null || ps.isEmpty()) { 75897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new IllegalArgumentException("permittedSubtrees are empty"); 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (excludedSubtrees != null) { 795c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson List<GeneralSubtree> es = excludedSubtrees.getSubtrees(); 805c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson if (es == null || es.isEmpty()) { 81897538a36c18f4db8f9f68ee566aec0bda842e9fElliott Hughes throw new IllegalArgumentException("excludedSubtrees are empty"); 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.permittedSubtrees = permittedSubtrees; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.excludedSubtrees = excludedSubtrees; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 88f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes private NameConstraints(GeneralSubtrees permittedSubtrees, 89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project GeneralSubtrees excludedSubtrees, byte[] encoding) { 90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this(permittedSubtrees, excludedSubtrees); 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.encoding = encoding; 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static NameConstraints decode(byte[] encoding) throws IOException { 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return (NameConstraints) ASN1.decode(encoding); 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 97f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 985c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson @Override public byte[] getEncoded() { 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (encoding == null) { 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project encoding = ASN1.encode(this); 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return encoding; 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1055c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** 1065c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * Prepare the data structure to speed up the checking process. 1075c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson */ 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private void prepareNames() { 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // array of lists with permitted General Names divided by type 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project permitted_names = new ArrayList[9]; 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (permittedSubtrees != null) { 1125c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (GeneralSubtree generalSubtree : permittedSubtrees.getSubtrees()) { 1135c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson GeneralName name = generalSubtree.getBase(); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int tag = name.getTag(); 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (permitted_names[tag] == null) { 1165c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson permitted_names[tag] = new ArrayList<GeneralName>(); 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project permitted_names[tag].add(name); 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // array of lists with excluded General Names divided by type 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project excluded_names = new ArrayList[9]; 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (excludedSubtrees != null) { 1245c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (GeneralSubtree generalSubtree : excludedSubtrees.getSubtrees()) { 1255c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson GeneralName name = generalSubtree.getBase(); 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int tag = name.getTag(); 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (excluded_names[tag] == null) { 1285c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson excluded_names[tag] = new ArrayList<GeneralName>(); 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project excluded_names[tag].add(name); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 134f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 1355c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson /** 1365c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * Returns the value of certificate extension 1375c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson */ 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private byte[] getExtensionValue(X509Certificate cert, String OID) { 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project byte[] bytes = cert.getExtensionValue(OID); 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (bytes == null) { 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return (byte[]) ASN1OctetString.getInstance().decode(bytes); 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 149f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Apply the name restrictions specified by this NameConstraints 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * instance to the subject distinguished name and subject alternative 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * names of specified X509Certificate. Restrictions apply only 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if specified name form is present in the certificate. 155f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * The restrictions are applied according the RFC 3280 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (see 4.2.1.11 Name Constraints), excepting that restrictions are applied 157f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * and to CA certificates, and to certificates which issuer and subject 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * names the same (i.e. method does not check if it CA's certificate or not, 159f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * or if the names differ or not. This check if it is needed should be done 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * by caller before calling this method). 1615c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * @param cert X.509 Certificate to be checked. 1625c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * @return true if the certificate is acceptable according 1635c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * these NameConstraints restrictions 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public boolean isAcceptable(X509Certificate cert) { 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (permitted_names == null) { 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project prepareNames(); 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 170f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes byte[] bytes = getExtensionValue(cert, "2.5.29.17"); 1715c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson List<GeneralName> names; 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 173f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes names = (bytes == null) 1745c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson ? new ArrayList<GeneralName>(1) // will check the subject field only 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project : ((GeneralNames) GeneralNames.ASN1.decode(bytes)).getNames(); 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // the certificate is broken; 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project e.printStackTrace(); 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((excluded_names[4] != null) || (permitted_names[4] != null)) { 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 183f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes names.add(new GeneralName(4, 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project cert.getSubjectX500Principal().getName())); 185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } catch (IOException e) { 186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // should never be happened 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return isAcceptable(names); 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 191f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1935c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson * Check if this list of names is acceptable according to this 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * NameConstraints object. 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1965c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson public boolean isAcceptable(List<GeneralName> names) { 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (permitted_names == null) { 198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project prepareNames(); 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 200f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 201f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // check map: shows which types of permitted alternative names are 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // presented in the certificate 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean[] types_presented = new boolean[9]; 204f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes // check map: shows if permitted name of presented type is found 205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // among the certificate's alternative names 206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project boolean[] permitted_found = new boolean[9]; 2075c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (GeneralName name : names) { 208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project int type = name.getTag(); 209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // search the name in excluded names 210adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (excluded_names[type] != null) { 2115c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (int i = 0; i < excluded_names[type].size(); i++) { 2125c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson if (excluded_names[type].get(i).isAcceptable(name)) { 213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Search the name in permitted names 218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // (if we already found the name of such type between the alt 219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // names - we do not need to check others) 220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if ((permitted_names[type] != null) && (!permitted_found[type])) { 221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project types_presented[type] = true; 2225c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (int i = 0; i < permitted_names[type].size(); i++) { 2235c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson if (permitted_names[type].get(i).isAcceptable(name)) { 224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // found one permitted name of such type 225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project permitted_found[type] = true; 226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2305c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (int type = 0; type < 9; type++) { 231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (types_presented[type] && !permitted_found[type]) { 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return false; 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return true; 236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2388216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes @Override public void dumpValue(StringBuilder sb, String prefix) { 2398216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes sb.append(prefix).append("Name Constraints: [\n"); 240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (permittedSubtrees != null) { 2418216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes sb.append(prefix).append(" Permitted: [\n"); 2425c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (GeneralSubtree generalSubtree : permittedSubtrees.getSubtrees()) { 2438216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes generalSubtree.dumpValue(sb, prefix + " "); 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2458216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes sb.append(prefix).append(" ]\n"); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (excludedSubtrees != null) { 2488216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes sb.append(prefix).append(" Excluded: [\n"); 2495c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson for (GeneralSubtree generalSubtree : excludedSubtrees.getSubtrees()) { 2508216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes generalSubtree.dumpValue(sb, prefix + " "); 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2528216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes sb.append(prefix).append(" ]\n"); 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 2548216dc1fd9d31867770439985c3d66570330e4c7Elliott Hughes sb.append('\n').append(prefix).append("]\n"); 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 256f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * X.509 NameConstraints encoder/decoder. 259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public static final ASN1Sequence ASN1 = new ASN1Sequence(new ASN1Type[] { 261f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes new ASN1Implicit(0, GeneralSubtrees.ASN1), 262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project new ASN1Implicit(1, GeneralSubtrees.ASN1) }) { 263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project { 264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setOptional(0); 265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project setOptional(1); 266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2685c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson @Override protected Object getDecodedObject(BerInputStream in) { 269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project Object[] values = (Object[]) in.content; 270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return new NameConstraints( 271f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes (GeneralSubtrees) values[0], 272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project (GeneralSubtrees) values[1], 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project in.getEncoded()); 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2765c27fb80ffd335aa45dc8829ba3ecbc18c01e4e8Jesse Wilson @Override protected void getValues(Object object, Object[] values) { 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project NameConstraints nc = (NameConstraints) object; 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project values[0] = nc.permittedSubtrees; 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project values[1] = nc.excludedSubtrees; 280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project }; 282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 283