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