1c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen/* 2c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Copyright (C) 2011 The Android Open Source Project 3c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * 4c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Licensed under the Apache License, Version 2.0 (the "License"); 5c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * you may not use this file except in compliance with the License. 6c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * You may obtain a copy of the License at 7c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * 8c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * http://www.apache.org/licenses/LICENSE-2.0 9c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * 10c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Unless required by applicable law or agreed to in writing, software 11c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * distributed under the License is distributed on an "AS IS" BASIS, 12c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * See the License for the specific language governing permissions and 14c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * limitations under the License. 15c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen */ 16c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 17c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenpackage com.android.nfc; 18c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 19c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.io.File; 20c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.io.FileDescriptor; 21c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.io.FileNotFoundException; 22c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.io.FileReader; 23c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.io.IOException; 24c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.io.PrintWriter; 25c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.util.ArrayList; 26c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport java.util.HashMap; 27c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 28c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport org.xmlpull.v1.XmlPullParser; 29c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport org.xmlpull.v1.XmlPullParserException; 30c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport org.xmlpull.v1.XmlPullParserFactory; 31c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 32c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.content.Context; 33c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.content.pm.ApplicationInfo; 34c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.content.pm.PackageInfo; 35c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.content.pm.PackageManager; 36c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.content.pm.Signature; 37c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.content.pm.PackageManager.NameNotFoundException; 38c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.os.Environment; 39c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenimport android.util.Log; 40c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 41c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenenpublic class NfceeAccessControl { 42c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen static final String TAG = "NfceeAccess"; 43410f4b955283be0187cd2933bdea07c66e101639Martijn Coenen static final boolean DBG = false; 44c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 45c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public static final String NFCEE_ACCESS_PATH = "/etc/nfcee_access.xml"; 46c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 47c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen /** 48c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Map of signatures to valid packages names, as read from nfcee_access.xml. 49c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * An empty list of package names indicates that any package 50c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * with this signature is allowed. 51c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen */ 52c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen final HashMap<Signature, String[]> mNfceeAccess; // contents final after onCreate() 53c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 54c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen /** 55c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Map from UID to NFCEE access, used as a cache. 56c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Note: if a UID contains multiple packages they must all be 57c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * signed with the same certificate so in effect UID == certificate 58c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * used to sign the package. 59c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen */ 60c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen final HashMap<Integer, Boolean> mUidCache; // contents guarded by this 61c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 62c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen final Context mContext; 63c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen final boolean mDebugPrintSignature; 64c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 65c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen NfceeAccessControl(Context context) { 66c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mContext = context; 67c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccess = new HashMap<Signature, String[]>(); 68c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mUidCache = new HashMap<Integer, Boolean>(); 69c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mDebugPrintSignature = parseNfceeAccess(); 70c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 71c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 72c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen /** 73c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Check if the {uid, pkg} combination may use NFCEE. 74c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Also verify with package manager that this {uid, pkg} combination 75c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * is valid if it is not cached. 76c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen */ 77c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public boolean check(int uid, String pkg) { 78c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 79c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Boolean cached = mUidCache.get(uid); 80c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (cached != null) { 81c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return cached; 82c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 83c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 84c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen boolean access = false; 85c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 86c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // Ensure the claimed package is present in the calling UID 87c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen PackageManager pm = mContext.getPackageManager(); 88c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen String[] pkgs = pm.getPackagesForUid(uid); 89c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (String uidPkg : pkgs) { 90c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (uidPkg.equals(pkg)) { 91c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // Ensure the package has access permissions 92c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (checkPackageNfceeAccess(pkg)) { 93c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen access = true; 94c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 95c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 96c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 97c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 98c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 99c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mUidCache.put(uid, access); 100c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return access; 101c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 102c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 103c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 104c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen /** 105c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Check if the given ApplicationInfo may use the NFCEE. 106c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Assumes ApplicationInfo came from package manager, 107c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * so no need to confirm {uid, pkg} is valid. 108c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen */ 109c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public boolean check(ApplicationInfo info) { 110c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 111c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Boolean access = mUidCache.get(info.uid); 112c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (access == null) { 113c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen access = checkPackageNfceeAccess(info.packageName); 114c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mUidCache.put(info.uid, access); 115c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 116c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return access; 117c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 118c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 119c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 120c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void invalidateCache() { 121c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 122c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mUidCache.clear(); 123c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 124c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 125c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 126c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen /** 127c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Check with package manager if the pkg may use NFCEE. 128c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Does not use cache. 129c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen */ 130c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen boolean checkPackageNfceeAccess(String pkg) { 131c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen PackageManager pm = mContext.getPackageManager(); 132c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen try { 133c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES); 134c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (info.signatures == null) { 135c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return false; 136c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 137c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 138c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (Signature s : info.signatures){ 139c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (s == null) { 140c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 141c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 142c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen String[] packages = mNfceeAccess.get(s); 143c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (packages == null) { 144c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 145c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 146c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (packages.length == 0) { 147c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // wildcard access 148c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (DBG) Log.d(TAG, "Granted NFCEE access to " + pkg + " (wildcard)"); 149c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return true; 150c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 151c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (String p : packages) { 152c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (pkg.equals(p)) { 153c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // explicit package access 154c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (DBG) Log.d(TAG, "Granted access to " + pkg + " (explicit)"); 155c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return true; 156c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 157c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 158c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 159c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 160c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (mDebugPrintSignature) { 161c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "denied NFCEE access for " + pkg + " with signature:"); 162c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (Signature s : info.signatures) { 163c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (s != null) { 164c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, s.toCharsString()); 165c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 166c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 167c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 168c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } catch (NameNotFoundException e) { 169c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // ignore 170c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 171c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return false; 172c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 173c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 174c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen /** 175c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Parse nfcee_access.xml, populate mNfceeAccess 176c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * Policy is to ignore unexpected XML elements and continue processing, 177c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * except for obvious errors within a <signer> group since they might cause 178c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * package names to by ignored and therefore wildcard access granted 179c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen * by mistake. Those errors invalidate the entire <signer> group. 180c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen */ 181c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen boolean parseNfceeAccess() { 182c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen File file = new File(Environment.getRootDirectory(), NFCEE_ACCESS_PATH); 183c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen FileReader reader = null; 184c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen boolean debug = false; 185c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen try { 186c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen reader = new FileReader(file); 187c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 188c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen XmlPullParser parser = factory.newPullParser(); 189c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen parser.setInput(reader); 190c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 191c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen int event; 192c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen ArrayList<String> packages = new ArrayList<String>(); 193c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Signature signature = null; 194c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); 195c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen while (true) { 196c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen event = parser.next(); 197c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen String tag = parser.getName(); 198c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (event == XmlPullParser.START_TAG && "signer".equals(tag)) { 199c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen signature = null; 200c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen packages.clear(); 201c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (int i = 0; i < parser.getAttributeCount(); i++) { 202c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if ("android:signature".equals(parser.getAttributeName(i))) { 203c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen signature = new Signature(parser.getAttributeValue(i)); 204c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 205c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 206c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 207c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (signature == null) { 208c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "signer tag is missing android:signature attribute, igorning"); 209c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 210c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 211c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (mNfceeAccess.containsKey(signature)) { 212c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "duplicate signature, ignoring"); 213c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen signature = null; 214c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 215c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 216c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } else if (event == XmlPullParser.END_TAG && "signer".equals(tag)) { 217c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (signature == null) { 218c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "mis-matched signer tag"); 219c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 220c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 221c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccess.put(signature, packages.toArray(new String[0])); 222c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen packages.clear(); 223c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } else if (event == XmlPullParser.START_TAG && "package".equals(tag)) { 224c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (signature == null) { 225c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "ignoring unnested packge tag"); 226c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 227c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 228c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen String name = null; 229c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (int i = 0; i < parser.getAttributeCount(); i++) { 230c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if ("android:name".equals(parser.getAttributeName(i))) { 231c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen name = parser.getAttributeValue(i); 232c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 233c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 234c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 235c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (name == null) { 236c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "package missing android:name, ignoring signer group"); 237c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen signature = null; // invalidate signer 238c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 239c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 240c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen // check for duplicate package names 241c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (packages.contains(name)) { 242c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "duplicate package name in signer group, ignoring"); 243c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen continue; 244c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 245c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen packages.add(name); 246c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } else if (event == XmlPullParser.START_TAG && "debug".equals(tag)) { 247c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen debug = true; 248c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } else if (event == XmlPullParser.END_DOCUMENT) { 249c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen break; 250c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 251c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 252c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } catch (XmlPullParserException e) { 253c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "failed to load NFCEE access list", e); 254c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccess.clear(); // invalidate entire access list 255c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } catch (FileNotFoundException e) { 256c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.w(TAG, "could not find " + NFCEE_ACCESS_PATH + ", no NFCEE access allowed"); 257c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } catch (IOException e) { 258c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.e(TAG, "Failed to load NFCEE access list", e); 259c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen mNfceeAccess.clear(); // invalidate entire access list 260c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } finally { 261c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen if (reader != null) { 262c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen try { 263c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen reader.close(); 264c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } catch (IOException e2) { } 265c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 266c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 267c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Log.i(TAG, "read " + mNfceeAccess.size() + " signature(s) for NFCEE access"); 268c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen return debug; 269c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 270c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen 271c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 272c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen pw.println("mNfceeAccess="); 273c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (Signature s : mNfceeAccess.keySet()) { 274c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen pw.printf("\t%s [", s.toCharsString()); 275c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen String[] ps = mNfceeAccess.get(s); 276c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (String p : ps) { 277c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen pw.printf("%s, ", p); 278c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 279c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen pw.println("]"); 280c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 281c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen synchronized (this) { 282c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen pw.println("mNfceeUidCache="); 283c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen for (Integer uid : mUidCache.keySet()) { 284c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen Boolean b = mUidCache.get(uid); 285c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen pw.printf("\t%d %s\n", uid, b); 286c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 287c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 288c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen } 289c19c065b6d0e1a088780c4dca27a1404d5926765Martijn Coenen} 290