1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this work for additional information regarding copyright ownership. 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (the "License"); you may not use this file except in compliance with 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the License. You may obtain a copy of the License at 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage java.security; 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ByteArrayInputStream; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.OptionalDataException; 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ObjectInputStream; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.ObjectOutputStream; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.Serializable; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.SocketPermission; 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.net.URL; 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertPath; 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.Certificate; 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertificateEncodingException; 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertificateException; 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.CertificateFactory; 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.cert.X509Certificate; 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List; 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport javax.security.auth.x500.X500Principal; 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.security.fortress.PolicyUtils; 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport org.apache.harmony.security.internal.nls.Messages; 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code CodeSource} encapsulates the location from where code is loaded and 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the certificates that were used to verify that code. This information is used 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * by {@code SecureClassLoader} to define protection domains for loaded classes. 46e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see SecureClassLoader 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see ProtectionDomain 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class CodeSource implements Serializable { 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static final long serialVersionUID = 4977541819976013951L; 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Location of this CodeSource object 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private URL location; 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Array of certificates assigned to this CodeSource object 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private transient java.security.cert.Certificate[] certs; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Array of CodeSigners 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private transient CodeSigner[] signers; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // SocketPermission() in implies() method takes to many time. 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Need to cache it for better performance. 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private transient SocketPermission sp; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Cached factory used to build CertPath-s in <code>getCodeSigners()</code>. 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private transient CertificateFactory factory; 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs a new instance of {@code CodeSource} with the specified 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code URL} and the {@code Certificate}s. 73e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param location 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the {@code URL} representing the location from where code is 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loaded, maybe {@code null}. 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param certs 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the {@code Certificate} used to verify the code, loaded from 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the specified {@code location}, maybe {@code null}. 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public CodeSource(URL location, Certificate[] certs) { 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.location = location; 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (certs != null) { 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.certs = new Certificate[certs.length]; 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(certs, 0, this.certs, 0, certs.length); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Constructs a new instance of {@code CodeSource} with the specified 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code URL} and the {@code CodeSigner}s. 92e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param location 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the {@code URL} representing the location from where code is 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * loaded, maybe {@code null}. 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param signers 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the {@code CodeSigner}s of the code, loaded from the specified 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code location}. Maybe {@code null}. 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public CodeSource(URL location, CodeSigner[] signers) { 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.location = location; 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (signers != null) { 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.signers = new CodeSigner[signers.length]; 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(signers, 0, this.signers, 0, signers.length); 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Compares the specified object with this {@code CodeSource} for equality. 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns {@code true} if the specified object is also an instance of 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code CodeSource}, points to the same {@code URL} location and the two 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * code sources encapsulate the same {@code Certificate}s. The order of the 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code Certificate}s is ignored by this method. 114e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param obj 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * object to be compared for equality with this {@code 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * CodeSource}. 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {@code true} if the specified object is equal to this {@code 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * CodeSource}, otherwise {@code false}. 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 121e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes @Override 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean equals(Object obj) { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (obj == this) { 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!(obj instanceof CodeSource)) { 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CodeSource that = (CodeSource) obj; 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.location != null) { 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (that.location == null) { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!this.location.equals(that.location)) { 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (that.location != null) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // do not use this.certs, as we also need to take care about 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // CodeSigners' certificates 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Certificate[] thizCerts = getCertificatesNoClone(); 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Certificate[] thatCerts = that.getCertificatesNoClone(); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!PolicyUtils.matchSubset(thizCerts, thatCerts)) { 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!PolicyUtils.matchSubset(thatCerts, thizCerts)) { 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the certificates of this {@code CodeSource}. If the 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@link #CodeSource(URL, CodeSigner[])} constructor was used to create 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this instance, the certificates are obtained from the supplied signers. 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * External modifications of the returned {@code Certificate[]} has no 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * impact on this {@code CodeSource}. 164e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the certificates of this {@code CodeSource} or {@code null} if 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * there is none. 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final Certificate[] getCertificates() { 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project getCertificatesNoClone(); 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (certs == null) { 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Certificate[] tmp = new Certificate[certs.length]; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(certs, 0, tmp, 0, certs.length); 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return tmp; 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Acts exactly as {@link #getCertificates()} does, but does not clone the 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // array before returning (and returns reference to <code>this.certs</code> 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // if this array is not null).<br> 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // @return a reference to the certificates array, or null if there are no 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // certificates associated. 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private Certificate[] getCertificatesNoClone() { 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (certs != null) { 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return certs; 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (signers == null) { 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Extract Certificates from the CodeSigner-s 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayList<Certificate> v = new ArrayList<Certificate>(); 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < signers.length; i++) { 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project v.addAll(signers[i].getSignerCertPath().getCertificates()); 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project certs = v.toArray(new Certificate[v.size()]); 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return certs; 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the {@code CodeSigner}s of this {@code CodeSource}. If the 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@link #CodeSource(URL, Certificate[])} constructor was used to create 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this instance, the signers are obtained from the supplied certificates. 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Only X.509 certificates are analyzed. 206e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the signers of this {@code CodeSource}, or {@code null} if there 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is none. 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final CodeSigner[] getCodeSigners() { 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (signers != null) { 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CodeSigner[] tmp = new CodeSigner[signers.length]; 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(signers, 0, tmp, 0, tmp.length); 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return tmp; 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if(certs == null || factory != null){ 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // factory != null means we've done this exercise already. 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project X500Principal prevIssuer = null; 222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayList<Certificate> list = new ArrayList<Certificate>(certs.length); 223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ArrayList<CodeSigner> asigners = new ArrayList<CodeSigner>(); 224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The presumption is that the chains of certificates are placed 226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // according to the CertPath agreement: 227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the lowest certs first; the CAs are at the last 229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // So the following loop scans trough the certs and checks 231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // that every next certificate is an Issuer of the previous one. 232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Any certificate that is not an Issuer of the previous one starts a 233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // new chain (== a new CertPath) 234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < certs.length; i++) { 236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!(certs[i] instanceof X509Certificate)) { 237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Only X509Certificate-s are taken into account - see API spec. 238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project continue; 239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project X509Certificate x509 = (X509Certificate) certs[i]; 241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (prevIssuer == null) { 242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // start a very first chain 243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevIssuer = x509.getIssuerX500Principal(); 244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project list.add(x509); 245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project X500Principal subj = x509.getSubjectX500Principal(); 247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!prevIssuer.equals(subj)) { 248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Ok, this ends the previous chain, 249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // so transform this one into CertPath ... 250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CertPath cpath = makeCertPath(list); 251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cpath != null) { 252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project asigners.add(new CodeSigner(cpath, null)); 253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ... and start a new one 255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project list.clear(); 256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project }// else { it's still the same chain } 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project prevIssuer = x509.getSubjectX500Principal(); 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project list.add(x509); 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!list.isEmpty()) { 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CertPath cpath = makeCertPath(list); 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cpath != null) { 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project asigners.add(new CodeSigner(cpath, null)); 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (asigners.isEmpty()) { 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 'signers' is 'null' already 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project signers = new CodeSigner[asigners.size()]; 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project asigners.toArray(signers); 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CodeSigner[] tmp = new CodeSigner[asigners.size()]; 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.arraycopy(signers, 0, tmp, 0, tmp.length); 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return tmp; 276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Makes an CertPath from a given List of X509Certificate-s. 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // @param list 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // @return CertPath, or null if CertPath cannot be made 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private CertPath makeCertPath(List<? extends Certificate> list) { 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (factory == null) { 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project factory = CertificateFactory.getInstance("X.509"); //$NON-NLS-1$ 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (CertificateException ex) { 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //? throw new Error("X.509 is a 'must be'", ex); 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return factory.generateCertPath(list); 292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (CertificateException ex) { 293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ignore(ex) 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return null; 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the location of this {@code CodeSource}. 300e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the location of this {@code CodeSource}, maybe {@code null}. 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public final URL getLocation() { 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return location; 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the hash code value for this {@code CodeSource}. 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns the same hash code for {@code CodeSource}s that are 310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * equal to each other as required by the general contract of 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@link Object#hashCode}. 312e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return the hash code value for this {@code CodeSource}. 314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see Object#equals(Object) 315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see CodeSource#equals(Object) 316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 317e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes @Override 318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public int hashCode() { 319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // hashCode() is undocumented there. Should we also use certs[i] to 321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // compute the hash ? 322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // for now, I don't take certs[] into account 323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return location == null ? 0 : location.hashCode(); 324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Indicates whether the specified code source is implied by this {@code 328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * CodeSource}. Returns {@code true} if all of the following conditions are 329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code true}, otherwise {@code false}: 330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <ul> 332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>{@code cs} is not {@code null} 333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource} has associated certificates, all 334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * certificates are present in {@code cs}. The certificates are extracted 335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from the signers if signers are present. 336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource}'s location is not {@code null}, the 337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * following conditions are checked 338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <ul> 339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>this {@code CodeSource}'s location is not {@code null} 340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>this {@code CodeSource}'s location protocol is equal to {@code cs}'s 341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * location protocol 342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource}'s location host is not {@code null}, the 343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * following conditions are checked 344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <ul> 345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>{@code cs}'s host is not {@code null} 346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>the {@link SocketPermission} of this {@code CodeSource}'s location 347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * host implies the {@code SocketPermission} of {@code cs}'s location host 348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </ul> 349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource}'s location port != -1 the port of {@code 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * cs}'s location is equal to this {@code CodeSource}'s location port 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>this {@code CodeSource}'s location file matches {@code cs}'s file 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * whereas special wildcard matching applies as described below 353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>this {@code CodeSource}'s location reference is equal to to {@code 354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * cs}'s location reference 355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </ul> 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </ul> 357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note: If this {@code CodeSource} has a {@code null} location and not any 359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * certificates, this method returns {@code true}. 360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <p> 361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Matching rules for the {@code CodeSource}'s location file: 362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <ul> 363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource}'s location file ends with {@code "/-"}, 364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then {@code cs}'s file must start with {@code CodeSource}'s location file 365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (exclusive the trailing '-') 366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource}'s location file ends with {@code "/*"}, 367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then {@code cs}'s file must start with {@code CodeSource}'s location file 368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (exclusive the trailing '*') and must not have any further '/' 369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource}'s location file ends with {@code "/"}, 370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * then {@code cs}'s file must start with {@code CodeSource}'s location file 371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>if this {@code CodeSource}'s location file does not end with {@code 372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * "/"}, then {@code cs}'s file must start with {@code CodeSource}'s 373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * location file with the '/' appended to it. 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </ul> 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Examples for locations that imply the location 376e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * "http://harmony.apache.org/milestones/M9/apache-harmony.jar": 377e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <pre> 379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http: 380e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * http://*/milestones/M9/* 381e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * http://*.apache.org/milestones/M9/* 382e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * http://harmony.apache.org/milestones/- 383e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * http://harmony.apache.org/milestones/M9/apache-harmony.jar 384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </pre> 385e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @param cs 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the code source to check. 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return {@code true} if the argument code source is implied by this 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code CodeSource}, otherwise {@code false}. 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public boolean implies(CodeSource cs) { 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Here, javadoc:N refers to the appropriate item in the API spec for 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // the CodeSource.implies() 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // The info was taken from the 1.5 final API spec 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // javadoc:1 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cs == null) { 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // javadoc:2 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // with a comment: the javadoc says only about certificates and does 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // not explicitly mention CodeSigners' certs. 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // It seems more convenient to use getCerts() to get the real 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // certificates - with a certificates got form the signers 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Certificate[] thizCerts = getCertificatesNoClone(); 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thizCerts != null) { 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Certificate[] thatCerts = cs.getCertificatesNoClone(); 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thatCerts == null 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project || !PolicyUtils.matchSubset(thizCerts, thatCerts)) { 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // javadoc:3 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.location != null) { 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //javadoc:3.1 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cs.location == null) { 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //javadoc:3.2 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.location.equals(cs.location)) { 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //javadoc:3.3 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!this.location.getProtocol().equals(cs.location.getProtocol())) { 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //javadoc:3.4 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String thisHost = this.location.getHost(); 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thisHost != null) { 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String thatHost = cs.location.getHost(); 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thatHost == null) { 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 1. According to the spec, an empty string will be considered 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // as "localhost" in the SocketPermission 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 2. 'file://' URLs will have an empty getHost() 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // so, let's make a special processing of localhost-s, I do 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // believe this'll improve performance of file:// code sources 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Don't have to evaluate both the boolean-s each time. 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // It's better to evaluate them directly under if() statement. 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // boolean thisIsLocalHost = thisHost.length() == 0 || "localhost".equals(thisHost); 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // boolean thatIsLocalHost = thatHost.length() == 0 || "localhost".equals(thatHost); 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // if( !(thisIsLocalHost && thatIsLocalHost) && 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // !thisHost.equals(thatHost)) { 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!((thisHost.length() == 0 || "localhost".equals(thisHost)) && (thatHost //$NON-NLS-1$ 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .length() == 0 || "localhost".equals(thatHost))) //$NON-NLS-1$ 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project && !thisHost.equals(thatHost)) { 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // Obvious, but very slow way.... 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // SocketPermission thisPerm = new SocketPermission( 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // this.location.getHost(), "resolve"); 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // SocketPermission thatPerm = new SocketPermission( 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // cs.location.getHost(), "resolve"); 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // if (!thisPerm.implies(thatPerm)) { 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // return false; 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // } 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // let's cache it: 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.sp == null) { 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.sp = new SocketPermission(thisHost, "resolve"); //$NON-NLS-1$ 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (cs.sp == null) { 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cs.sp = new SocketPermission(thatHost, "resolve"); //$NON-NLS-1$ 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!this.sp.implies(cs.sp)) { 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } // if( ! this.location.getHost().equals(cs.location.getHost()) 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } // if (this.location.getHost() != null) 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //javadoc:3.5 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.location.getPort() != -1) { 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.location.getPort() != cs.location.getPort()) { 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //javadoc:3.6 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String thisFile = this.location.getFile(); 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String thatFile = cs.location.getFile(); 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thisFile.endsWith("/-")) { //javadoc:3.6."/-" //$NON-NLS-1$ 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!thatFile.startsWith(thisFile.substring(0, thisFile 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .length() - 2))) { 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else if (thisFile.endsWith("/*")) { //javadoc:3.6."/*" //$NON-NLS-1$ 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!thatFile.startsWith(thisFile.substring(0, thisFile 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project .length() - 2))) { 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // no further separators(s) allowed 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (thatFile.indexOf("/", thisFile.length() - 1) != -1) { //$NON-NLS-1$ 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // javadoc:3.6."/" 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!thisFile.equals(thatFile)) { 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!thisFile.endsWith("/")) { //$NON-NLS-1$ 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!thatFile.equals(thisFile + "/")) { //$NON-NLS-1$ 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 516f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //javadoc:3.7 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (this.location.getRef() != null) { 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!this.location.getRef().equals(cs.location.getRef())) { 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return false; 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // ok, every check was made, and they all were successful. 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // it's ok to return true. 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } // if this.location != null 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // javadoc: a note about CodeSource with null location and null Certs 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // is applicable here 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return true; 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns a string containing a concise, human-readable description of the 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * this {@code CodeSource} including its location, its certificates and its 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * signers. 541e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes * 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @return a printable representation for this {@code CodeSource}. 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 544e7637fe9734c4e3bece51db6773505c04e49fabaElliott Hughes @Override 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public String toString() { 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuilder buf = new StringBuilder(); 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append("CodeSource, url="); //$NON-NLS-1$ 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append(location == null ? "<null>" : location.toString()); //$NON-NLS-1$ 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (certs == null) { 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append(", <no certificates>"); //$NON-NLS-1$ 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append("\nCertificates [\n"); //$NON-NLS-1$ 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < certs.length; i++) { 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append(i + 1).append(") ").append(certs[i]).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$ 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append("]\n"); //$NON-NLS-1$ 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (signers != null) { 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append("\nCodeSigners [\n"); //$NON-NLS-1$ 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < signers.length; i++) { 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append(i + 1).append(") ").append(signers[i]).append("\n"); //$NON-NLS-1$ //$NON-NLS-2$ 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buf.append("]\n"); //$NON-NLS-1$ 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return buf.toString(); 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void writeObject(ObjectOutputStream oos) throws IOException { 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oos.defaultWriteObject(); 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (certs == null || certs.length == 0) { 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oos.writeInt(0); 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oos.writeInt(certs.length); 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < certs.length; i++) { 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oos.writeUTF(certs[i].getType()); 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] data = certs[i].getEncoded(); 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // hope there are no certificates with 'data==null' 582f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oos.writeInt(data.length); 583f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oos.write(data); 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (CertificateEncodingException ex) { 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw (IOException) new IOException( 586f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Messages.getString("security.18")).initCause(ex); //$NON-NLS-1$ 587f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 588f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 589f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 590f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (signers != null && signers.length != 0) { 591f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project oos.writeObject(signers); 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 594f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 595f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void readObject(ObjectInputStream ois) throws IOException, 596f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ClassNotFoundException { 597f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 598f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ois.defaultReadObject(); 599f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 600f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int certsCount = ois.readInt(); 601f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project certs = null; 602f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (certsCount != 0) { 603f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project certs = new Certificate[certsCount]; 604f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < certsCount; i++) { 605f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project String type = ois.readUTF(); 606f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project CertificateFactory factory; 607f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 608f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project factory = CertificateFactory.getInstance(type); 609f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (CertificateException ex) { 610f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw new ClassNotFoundException( 611f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Messages.getString("security.19", type), //$NON-NLS-1$ 612f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ex); 613f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 614f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int dataLen = ois.readInt(); 615f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project byte[] data = new byte[dataLen]; 616f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ois.readFully(data); 617f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ByteArrayInputStream bais = new ByteArrayInputStream(data); 618f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 619f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project certs[i] = factory.generateCertificate(bais); 620f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (CertificateException ex) { 621f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw (IOException) new IOException( 622f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project Messages.getString("security.1A")).initCause(ex); //$NON-NLS-1$ 623f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 624f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 625f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 626f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project try { 627f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project signers = (CodeSigner[]) ois.readObject(); 628f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } catch (OptionalDataException ex) { 629f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!ex.eof) { 630f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project throw ex; 631f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 632f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project // no signers (ex.eof==true <= no data left) is allowed 633f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 634f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 635f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 636