/*
 * 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 = true;

    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<Signature, String[]> 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<Integer, Boolean> mUidCache;  // contents guarded by this

    final Context mContext;
    final boolean mDebugPrintSignature;

    NfceeAccessControl(Context context) {
        mContext = context;
        mNfceeAccess = new HashMap<Signature, String[]>();
        mUidCache = new HashMap<Integer, Boolean>();
        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 <signer> group since they might cause
     * package names to by ignored and therefore wildcard access granted
     * by mistake. Those errors invalidate the entire <signer> 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<String> packages = new ArrayList<String>();
            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);
            }
        }
    }
}
