access control java_NfceeAccessControl.java

/*

* Copyright (C) 2011 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package com.android.nfc;

import java.io.File;

import java.io.FileDescriptor;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.ArrayList;

import java.util.HashMap;

import org.xmlpull.v1.XmlPullParser;

import org.xmlpull.v1.XmlPullParserException;

import org.xmlpull.v1.XmlPullParserFactory;

import android.content.Context;

import android.content.pm.ApplicationInfo;

import android.content.pm.PackageInfo;

import android.content.pm.PackageManager;

import android.content.pm.Signature;

import android.content.pm.PackageManager.NameNotFoundException;

import android.os.Environment;

import android.util.Log;

public class NfceeAccessControl {

static final String TAG = "NfceeAccess";

static final boolean DBG = false;

public static final String NFCEE_ACCESS_PATH = "/etc/nfcee_access.xml";

/**

* Map of signatures to valid packages names, as read from nfcee_access.xml.

* An empty list of package names indicates that any package

* with this signature is allowed.

*/

final HashMapmNfceeAccess; // contents final after onCreate()

/**

* Map from UID to NFCEE access, used as a cache.

* Note: if a UID contains multiple packages they must all be

* signed with the same certificate so in effect UID == certificate

* used to sign the package.

*/

final HashMapmUidCache; // contents guarded by this

final Context mContext;

final boolean mDebugPrintSignature;

NfceeAccessControl(Context context) {

mContext = context;

mNfceeAccess = new HashMap();

mUidCache = new HashMap();

mDebugPrintSignature = parseNfceeAccess();

}

/**

* Check if the {uid, pkg} combination may use NFCEE.

* Also verify with package manager that this {uid, pkg} combination

* is valid if it is not cached.

*/

public boolean check(int uid, String pkg) {

synchronized (this) {

Boolean cached = mUidCache.get(uid);

if (cached != null) {

return cached;

}

boolean access = false;

// Ensure the claimed package is present in the calling UID

PackageManager pm = mContext.getPackageManager();

String[] pkgs = pm.getPackagesForUid(uid);

for (String uidPkg : pkgs) {

if (uidPkg.equals(pkg)) {

// Ensure the package has access permissions

if (checkPackageNfceeAccess(pkg)) {

access = true;

}

break;

}

}

mUidCache.put(uid, access);

return access;

}

}

/**

* Check if the given ApplicationInfo may use the NFCEE.

* Assumes ApplicationInfo came from package manager,

* so no need to confirm {uid, pkg} is valid.

*/

public boolean check(ApplicationInfo info) {

synchronized (this) {

Boolean access = mUidCache.get(info.uid);

if (access == null) {

access = checkPackageNfceeAccess(info.packageName);

mUidCache.put(info.uid, access);

}

return access;

}

}

public void invalidateCache() {

synchronized (this) {

mUidCache.clear();

}

}

/**

* Check with package manager if the pkg may use NFCEE.

* Does not use cache.

*/

boolean checkPackageNfceeAccess(String pkg) {

PackageManager pm = mContext.getPackageManager();

try {

PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);

if (info.signatures == null) {

return false;

}

for (Signature s : info.signatures){

if (s == null) {

continue;

}

String[] packages = mNfceeAccess.get(s);

if (packages == null) {

continue;

}

if (packages.length == 0) {

// wildcard access

if (DBG) Log.d(TAG, "Granted NFCEE access to " + pkg + " (wildcard)");

return true;

}

for (String p : packages) {

if (pkg.equals(p)) {

// explicit package access

if (DBG) Log.d(TAG, "Granted access to " + pkg + " (explicit)");

return true;

}

}

}

if (mDebugPrintSignature) {

Log.w(TAG, "denied NFCEE access for " + pkg + " with signature:");

for (Signature s : info.signatures) {

if (s != null) {

Log.w(TAG, s.toCharsString());

}

}

}

} catch (NameNotFoundException e) {

// ignore

}

return false;

}

/**

* Parse nfcee_access.xml, populate mNfceeAccess

* Policy is to ignore unexpected XML elements and continue processing,

* except for obvious errors within a group since they might cause

* package names to by ignored and therefore wildcard access granted

* by mistake. Those errors invalidate the entire group.

*/

boolean parseNfceeAccess() {

File file = new File(Environment.getRootDirectory(), NFCEE_ACCESS_PATH);

FileReader reader = null;

boolean debug = false;

try {

reader = new FileReader(file);

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

XmlPullParser parser = factory.newPullParser();

parser.setInput(reader);

int event;

ArrayListpackages = new ArrayList();

Signature signature = null;

parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);

while (true) {

event = parser.next();

String tag = parser.getName();

if (event == XmlPullParser.START_TAG && "signer".equals(tag)) {

signature = null;

packages.clear();

for (int i = 0; i < parser.getAttributeCount(); i++) {

if ("android:signature".equals(parser.getAttributeName(i))) {

signature = new Signature(parser.getAttributeValue(i));

break;

}

}

if (signature == null) {

Log.w(TAG, "signer tag is missing android:signature attribute, igorning");

continue;

}

if (mNfceeAccess.containsKey(signature)) {

Log.w(TAG, "duplicate signature, ignoring");

signature = null;

continue;

}

} else if (event == XmlPullParser.END_TAG && "signer".equals(tag)) {

if (signature == null) {

Log.w(TAG, "mis-matched signer tag");

continue;

}

mNfceeAccess.put(signature, packages.toArray(new String[0]));

packages.clear();

} else if (event == XmlPullParser.START_TAG && "package".equals(tag)) {

if (signature == null) {

Log.w(TAG, "ignoring unnested packge tag");

continue;

}

String name = null;

for (int i = 0; i < parser.getAttributeCount(); i++) {

if ("android:name".equals(parser.getAttributeName(i))) {

name = parser.getAttributeValue(i);

break;

}

}

if (name == null) {

Log.w(TAG, "package missing android:name, ignoring signer group");

signature = null; // invalidate signer

continue;

}

// check for duplicate package names

if (packages.contains(name)) {

Log.w(TAG, "duplicate package name in signer group, ignoring");

continue;

}

packages.add(name);

} else if (event == XmlPullParser.START_TAG && "debug".equals(tag)) {

debug = true;

} else if (event == XmlPullParser.END_DOCUMENT) {

break;

}

}

} catch (XmlPullParserException e) {

Log.w(TAG, "failed to load NFCEE access list", e);

mNfceeAccess.clear(); // invalidate entire access list

} catch (FileNotFoundException e) {

Log.w(TAG, "could not find " + NFCEE_ACCESS_PATH + ", no NFCEE access allowed");

} catch (IOException e) {

Log.e(TAG, "Failed to load NFCEE access list", e);

mNfceeAccess.clear(); // invalidate entire access list

} finally {

if (reader != null) {

try {

reader.close();

} catch (IOException e2) { }

}

}

Log.i(TAG, "read " + mNfceeAccess.size() + " signature(s) for NFCEE access");

return debug;

}

public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {

pw.println("mNfceeAccess=");

for (Signature s : mNfceeAccess.keySet()) {

pw.printf("\t%s [", s.toCharsString());

String[] ps = mNfceeAccess.get(s);

for (String p : ps) {

pw.printf("%s, ", p);

}

pw.println("]");

}

synchronized (this) {

pw.println("mNfceeUidCache=");

for (Integer uid : mUidCache.keySet()) {

Boolean b = mUidCache.get(uid);

pw.printf("\t%d %s\n", uid, b);

}

}

}

}

Java程序

|

290行

|

10.67 KB

/*

* Copyright (C) 2011 The Android Open Source Project

*

* Licensed under the Apache License, Version 2.0 (the "License");

* you may not use this file except in compliance with the License.

* You may obtain a copy of the License at

*

* http://www.apache.org/licenses/LICENSE-2.0

*

* Unless required by applicable law or agreed to in writing, software

* distributed under the License is distributed on an "AS IS" BASIS,

* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

* See the License for the specific language governing permissions and

* limitations under the License.

*/

package com.android.nfc;

import java.io.File;

import java.io.FileDescriptor;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.io.PrintWriter;

import java.util.ArrayList;

import java.util.HashMap;

import org.xmlpull.v1.XmlPullParser;

import org.xmlpull.v1.XmlPullParserException;

import org.xmlpull.v1.XmlPullParserFactory;

import android.content.Context;

import android.content.pm.ApplicationInfo;

import android.content.pm.PackageInfo;

import android.content.pm.PackageManager;

import android.content.pm.Signature;

import android.content.pm.PackageManager.NameNotFoundException;

import android.os.Environment;

import android.util.Log;

public class NfceeAccessControl {

static final String TAG = "NfceeAccess";

static final boolean DBG = false;

public static final String NFCEE_ACCESS_PATH = "/etc/nfcee_access.xml";

/**

* Map of signatures to valid packages names, as read from nfcee_access.xml.

* An empty list of package names indicates that any package

* with this signature is allowed.

*/

final HashMap mNfceeAccess; // contents final after onCreate()

/**

* Map from UID to NFCEE access, used as a cache.

* Note: if a UID contains multiple packages they must all be

* signed with the same certificate so in effect UID == certificate

* used to sign the package.

*/

final HashMap mUidCache; // contents guarded by this

final Context mContext;

final boolean mDebugPrintSignature;

NfceeAccessControl(Context context) {

mContext = context;

mNfceeAccess = new HashMap();

mUidCache = new HashMap();

mDebugPrintSignature = parseNfceeAccess();

}

/**

* Check if the {uid, pkg} combination may use NFCEE.

* Also verify with package manager that this {uid, pkg} combination

* is valid if it is not cached.

*/

public boolean check(int uid, String pkg) {

synchronized (this) {

Boolean cached = mUidCache.get(uid);

if (cached != null) {

return cached;

}

boolean access = false;

// Ensure the claimed package is present in the calling UID

PackageManager pm = mContext.getPackageManager();

String[] pkgs = pm.getPackagesForUid(uid);

for (String uidPkg : pkgs) {

if (uidPkg.equals(pkg)) {

// Ensure the package has access permissions

if (checkPackageNfceeAccess(pkg)) {

access = true;

}

break;

}

}

mUidCache.put(uid, access);

return access;

}

}

/**

* Check if the given ApplicationInfo may use the NFCEE.

* Assumes ApplicationInfo came from package manager,

* so no need to confirm {uid, pkg} is valid.

*/

public boolean check(ApplicationInfo info) {

synchronized (this) {

Boolean access = mUidCache.get(info.uid);

if (access == null) {

access = checkPackageNfceeAccess(info.packageName);

mUidCache.put(info.uid, access);

}

return access;

}

}

public void invalidateCache() {

synchronized (this) {

mUidCache.clear();

}

}

/**

* Check with package manager if the pkg may use NFCEE.

* Does not use cache.

*/

boolean checkPackageNfceeAccess(String pkg) {

PackageManager pm = mContext.getPackageManager();

try {

PackageInfo info = pm.getPackageInfo(pkg, PackageManager.GET_SIGNATURES);

if (info.signatures == null) {

return false;

}

for (Signature s : info.signatures){

if (s == null) {

continue;

}

String[] packages = mNfceeAccess.get(s);

if (packages == null) {

continue;

}

if (packages.length == 0) {

// wildcard access

if (DBG) Log.d(TAG, "Granted NFCEE access to " + pkg + " (wildcard)");

return true;

}

for (String p : packages) {

if (pkg.equals(p)) {

// explicit package access

if (DBG) Log.d(TAG, "Granted access to " + pkg + " (explicit)");

return true;

}

}

}

if (mDebugPrintSignature) {

Log.w(TAG, "denied NFCEE access for " + pkg + " with signature:");

for (Signature s : info.signatures) {

if (s != null) {

Log.w(TAG, s.toCharsString());

}

}

}

} catch (NameNotFoundException e) {

// ignore

}

return false;

}

/**

* Parse nfcee_access.xml, populate mNfceeAccess

* Policy is to ignore unexpected XML elements and continue processing,

* except for obvious errors within a group since they might cause

* package names to by ignored and therefore wildcard access granted

* by mistake. Those errors invalidate the entire group.

*/

boolean parseNfceeAccess() {

File file = new File(Environment.getRootDirectory(), NFCEE_ACCESS_PATH);

FileReader reader = null;

boolean debug = false;

try {

reader = new FileReader(file);

XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

XmlPullParser parser = factory.newPullParser();

parser.setInput(reader);

int event;

ArrayList packages = new ArrayList();

Signature signature = null;

parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);

while (true) {

event = parser.next();

String tag = parser.getName();

if (event == XmlPullParser.START_TAG && "signer".equals(tag)) {

signature = null;

packages.clear();

for (int i = 0; i < parser.getAttributeCount(); i++) {

if ("android:signature".equals(parser.getAttributeName(i))) {

signature = new Signature(parser.getAttributeValue(i));

break;

}

}

if (signature == null) {

Log.w(TAG, "signer tag is missing android:signature attribute, igorning");

continue;

}

if (mNfceeAccess.containsKey(signature)) {

Log.w(TAG, "duplicate signature, ignoring");

signature = null;

continue;

}

} else if (event == XmlPullParser.END_TAG && "signer".equals(tag)) {

if (signature == null) {

Log.w(TAG, "mis-matched signer tag");

continue;

}

mNfceeAccess.put(signature, packages.toArray(new String[0]));

packages.clear();

} else if (event == XmlPullParser.START_TAG && "package".equals(tag)) {

if (signature == null) {

Log.w(TAG, "ignoring unnested packge tag");

continue;

}

String name = null;

for (int i = 0; i < parser.getAttributeCount(); i++) {

if ("android:name".equals(parser.getAttributeName(i))) {

name = parser.getAttributeValue(i);

break;

}

}

if (name == null) {

Log.w(TAG, "package missing android:name, ignoring signer group");

signature = null; // invalidate signer

continue;

}

// check for duplicate package names

if (packages.contains(name)) {

Log.w(TAG, "duplicate package name in signer group, ignoring");

continue;

}

packages.add(name);

} else if (event == XmlPullParser.START_TAG && "debug".equals(tag)) {

debug = true;

} else if (event == XmlPullParser.END_DOCUMENT) {

break;

}

}

} catch (XmlPullParserException e) {

Log.w(TAG, "failed to load NFCEE access list", e);

mNfceeAccess.clear(); // invalidate entire access list

} catch (FileNotFoundException e) {

Log.w(TAG, "could not find " + NFCEE_ACCESS_PATH + ", no NFCEE access allowed");

} catch (IOException e) {

Log.e(TAG, "Failed to load NFCEE access list", e);

mNfceeAccess.clear(); // invalidate entire access list

} finally {

if (reader != null) {

try {

reader.close();

} catch (IOException e2) { }

}

}

Log.i(TAG, "read " + mNfceeAccess.size() + " signature(s) for NFCEE access");

return debug;

}

public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {

pw.println("mNfceeAccess=");

for (Signature s : mNfceeAccess.keySet()) {

pw.printf("\t%s [", s.toCharsString());

String[] ps = mNfceeAccess.get(s);

for (String p : ps) {

pw.printf("%s, ", p);

}

pw.println("]");

}

synchronized (this) {

pw.println("mNfceeUidCache=");

for (Integer uid : mUidCache.keySet()) {

Boolean b = mUidCache.get(uid);

pw.printf("\t%d %s\n", uid, b);

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值