1cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root/* 2cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Copyright (C) 2011 The Android Open Source Project 3cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * 4cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Licensed under the Apache License, Version 2.0 (the "License"); 5cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * you may not use this file except in compliance with the License. 6cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * You may obtain a copy of the License at 7cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * 8cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * http://www.apache.org/licenses/LICENSE-2.0 9cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * 10cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Unless required by applicable law or agreed to in writing, software 11cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * distributed under the License is distributed on an "AS IS" BASIS, 12cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * See the License for the specific language governing permissions and 14cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * limitations under the License. 15cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root */ 16cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 17cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootpackage com.android.server.pm; 18cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 19cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport com.android.internal.util.XmlUtils; 20cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 21cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport org.xmlpull.v1.XmlPullParser; 22cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport org.xmlpull.v1.XmlPullParserException; 23cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport org.xmlpull.v1.XmlSerializer; 24cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 25cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport android.content.pm.Signature; 26cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport android.util.Log; 27cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 28cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport java.io.IOException; 29cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootimport java.util.ArrayList; 30cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 31cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootclass PackageSignatures { 32cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root Signature[] mSignatures; 33cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 34cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageSignatures(PackageSignatures orig) { 35cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (orig != null && orig.mSignatures != null) { 36cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures = orig.mSignatures.clone(); 37cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 38cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 39cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 40cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageSignatures(Signature[] sigs) { 41cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root assignSignatures(sigs); 42cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 43cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 44cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageSignatures() { 45cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 46cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 47cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root void writeXml(XmlSerializer serializer, String tagName, 48cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root ArrayList<Signature> pastSignatures) throws IOException { 49cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (mSignatures == null) { 50cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root return; 51cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 52cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.startTag(null, tagName); 53cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.attribute(null, "count", 54cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root Integer.toString(mSignatures.length)); 55cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root for (int i=0; i<mSignatures.length; i++) { 56cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.startTag(null, "cert"); 57cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root final Signature sig = mSignatures[i]; 58cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root final int sigHash = sig.hashCode(); 59cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root final int numPast = pastSignatures.size(); 60cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root int j; 61cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root for (j=0; j<numPast; j++) { 62cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root Signature pastSig = pastSignatures.get(j); 63cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) { 64cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.attribute(null, "index", Integer.toString(j)); 65cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root break; 66cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 67cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 68cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (j >= numPast) { 69cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root pastSignatures.add(sig); 70cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.attribute(null, "index", Integer.toString(numPast)); 71cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.attribute(null, "key", sig.toCharsString()); 72cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 73cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.endTag(null, "cert"); 74cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 75cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root serializer.endTag(null, tagName); 76cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 77cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 78cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures) 79cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root throws IOException, XmlPullParserException { 80cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root String countStr = parser.getAttributeValue(null, "count"); 81cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (countStr == null) { 82cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 83cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root "Error in package manager settings: <signatures> has" 84cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + " no count at " + parser.getPositionDescription()); 85cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root XmlUtils.skipCurrentTag(parser); 86cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 87cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root final int count = Integer.parseInt(countStr); 88cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures = new Signature[count]; 89cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root int pos = 0; 90cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 91cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root int outerDepth = parser.getDepth(); 92cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root int type; 93cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root while ((type=parser.next()) != XmlPullParser.END_DOCUMENT 94cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root && (type != XmlPullParser.END_TAG 95cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root || parser.getDepth() > outerDepth)) { 96cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (type == XmlPullParser.END_TAG 97cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root || type == XmlPullParser.TEXT) { 98cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root continue; 99cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 100cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 101cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root String tagName = parser.getName(); 102cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (tagName.equals("cert")) { 103cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (pos < count) { 104cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root String index = parser.getAttributeValue(null, "index"); 105cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (index != null) { 106cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root try { 107cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root int idx = Integer.parseInt(index); 108cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root String key = parser.getAttributeValue(null, "key"); 109cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (key == null) { 110cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (idx >= 0 && idx < pastSignatures.size()) { 111cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root Signature sig = pastSignatures.get(idx); 112cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (sig != null) { 113cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures[pos] = pastSignatures.get(idx); 114cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root pos++; 115cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } else { 116cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 117cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root "Error in package manager settings: <cert> " 118cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + "index " + index + " is not defined at " 119cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + parser.getPositionDescription()); 120cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 121cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } else { 122cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 123cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root "Error in package manager settings: <cert> " 124cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + "index " + index + " is out of bounds at " 125cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + parser.getPositionDescription()); 126cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 127cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } else { 128cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root while (pastSignatures.size() <= idx) { 129cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root pastSignatures.add(null); 130cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 131cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root Signature sig = new Signature(key); 132cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root pastSignatures.set(idx, sig); 133cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures[pos] = sig; 134cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root pos++; 135cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 136cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } catch (NumberFormatException e) { 137cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 138cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root "Error in package manager settings: <cert> " 139cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + "index " + index + " is not a number at " 140cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + parser.getPositionDescription()); 1411137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root } catch (IllegalArgumentException e) { 1421137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 1431137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root "Error in package manager settings: <cert> " 1441137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root + "index " + index + " has an invalid signature at " 1451137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root + parser.getPositionDescription() + ": " 1461137341885d8dc451dddc2e01319fb0fab00bbc3Kenny Root + e.getMessage()); 147cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 148cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } else { 149cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 150cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root "Error in package manager settings: <cert> has" 151cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + " no index at " + parser.getPositionDescription()); 152cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 153cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } else { 154cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 155cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root "Error in package manager settings: too " 156cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + "many <cert> tags, expected " + count 157cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + " at " + parser.getPositionDescription()); 158cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 159cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } else { 160cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root PackageManagerService.reportSettingsProblem(Log.WARN, 161cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root "Unknown element under <cert>: " 162cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root + parser.getName()); 163cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 164cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root XmlUtils.skipCurrentTag(parser); 165cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 166cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 167cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (pos < count) { 168cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root // Should never happen -- there is an error in the written 169cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root // settings -- but if it does we don't want to generate 170cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root // a bad array. 171cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root Signature[] newSigs = new Signature[pos]; 172cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root System.arraycopy(mSignatures, 0, newSigs, 0, pos); 173cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures = newSigs; 174cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 175cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 176cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 177cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root void assignSignatures(Signature[] sigs) { 178cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (sigs == null) { 179cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures = null; 180cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root return; 181cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 182cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures = new Signature[sigs.length]; 183cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root for (int i=0; i<sigs.length; i++) { 184cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root mSignatures[i] = sigs[i]; 185cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 186cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 187cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root 188cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root @Override 189cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root public String toString() { 190cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root StringBuffer buf = new StringBuffer(128); 191cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root buf.append("PackageSignatures{"); 192cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root buf.append(Integer.toHexString(System.identityHashCode(this))); 193cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root buf.append(" ["); 194cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (mSignatures != null) { 195cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root for (int i=0; i<mSignatures.length; i++) { 196cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root if (i > 0) buf.append(", "); 197cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root buf.append(Integer.toHexString( 198cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root System.identityHashCode(mSignatures[i]))); 199cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 200cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 201cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root buf.append("]}"); 202cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root return buf.toString(); 203cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root } 204cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root}