/*
 * 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.settings;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.security.Credentials;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
import android.security.KeyStore;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.android.internal.widget.LockPatternUtils;
import com.android.org.bouncycastle.asn1.ASN1InputStream;
import com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.security.ConfigureKeyGuardDialog;
import com.android.settings.vpn2.VpnUtils;

import java.io.ByteArrayInputStream;
import java.io.IOException;

import sun.security.util.ObjectIdentifier;
import sun.security.x509.AlgorithmId;

/**
 * CredentialStorage handles KeyStore reset, unlock, and install.
 *
 * CredentialStorage has a pretty convoluted state machine to migrate
 * from the old style separate keystore password to a new key guard
 * based password, as well as to deal with setting up the key guard if
 * necessary.
 *
 * KeyStore: UNINITALIZED
 * KeyGuard: OFF
 * Action:   set up key guard
 * Notes:    factory state
 *
 * KeyStore: UNINITALIZED
 * KeyGuard: ON
 * Action:   confirm key guard
 * Notes:    user had key guard but no keystore and upgraded from pre-ICS
 * OR user had key guard and pre-ICS keystore password which was then reset
 *
 * KeyStore: LOCKED
 * KeyGuard: OFF/ON
 * Action:   old unlock dialog
 * Notes:    assume old password, need to use it to unlock.
 * if unlock, ensure key guard before install.
 * if reset, treat as UNINITALIZED/OFF
 *
 * KeyStore: UNLOCKED
 * KeyGuard: OFF
 * Action:   set up key guard
 * Notes:    ensure key guard, then proceed
 *
 * KeyStore: UNLOCKED
 * keyguard: ON
 * Action:   normal unlock/install
 * Notes:    this is the common case
 */
public final class CredentialStorage extends Activity {

    private static final String TAG = "CredentialStorage";

    public static final String ACTION_UNLOCK = "com.android.credentials.UNLOCK";
    public static final String ACTION_INSTALL = "com.android.credentials.INSTALL";
    public static final String ACTION_RESET = "com.android.credentials.RESET";

    // This is the minimum acceptable password quality.  If the current password quality is
    // lower than this, keystore should not be activated.
    public static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;

    private static final int CONFIRM_KEY_GUARD_REQUEST = 1;
    private static final int CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST = 2;

    private final KeyStore mKeyStore = KeyStore.getInstance();

    /**
     * When non-null, the bundle containing credentials to install.
     */
    private Bundle mInstallBundle;

    /**
     * After unsuccessful KeyStore.unlock, the number of unlock
     * attempts remaining before the KeyStore will reset itself.
     *
     * Reset to -1 on successful unlock or reset.
     */
    private int mRetriesRemaining = -1;

    @Override
    protected void onResume() {
        super.onResume();

        Intent intent = getIntent();
        String action = intent.getAction();
        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
        if (!userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
            if (ACTION_RESET.equals(action)) {
                new ResetDialog();
            } else {
                if (ACTION_INSTALL.equals(action) && checkCallerIsCertInstallerOrSelfInProfile()) {
                    mInstallBundle = intent.getExtras();
                }
                // ACTION_UNLOCK also handled here in addition to ACTION_INSTALL
                handleUnlockOrInstall();
            }
        } else {
            // Users can set a screen lock if there is none even if they can't modify the
            // credentials store.
            if (ACTION_UNLOCK.equals(action) && mKeyStore.state() == KeyStore.State.UNINITIALIZED) {
                ensureKeyGuard();
            } else {
                finish();
            }
        }
    }

    /**
     * Based on the current state of the KeyStore and key guard, try to
     * make progress on unlocking or installing to the keystore.
     */
    private void handleUnlockOrInstall() {
        // something already decided we are done, do not proceed
        if (isFinishing()) {
            return;
        }
        switch (mKeyStore.state()) {
            case UNINITIALIZED: {
                ensureKeyGuard();
                return;
            }
            case LOCKED: {
                new UnlockDialog();
                return;
            }
            case UNLOCKED: {
                if (!checkKeyGuardQuality()) {
                    final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
                    dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
                    return;
                }
                installIfAvailable();
                finish();
                return;
            }
        }
    }

    /**
     * Make sure the user enters the key guard to set or change the
     * keystore password. This can be used in UNINITIALIZED to set the
     * keystore password or UNLOCKED to change the password (as is the
     * case after unlocking with an old-style password).
     */
    private void ensureKeyGuard() {
        if (!checkKeyGuardQuality()) {
            // key guard not setup, doing so will initialize keystore
            final ConfigureKeyGuardDialog dialog = new ConfigureKeyGuardDialog();
            dialog.show(getFragmentManager(), ConfigureKeyGuardDialog.TAG);
            // will return to onResume after Activity
            return;
        }
        // force key guard confirmation
        if (confirmKeyGuard(CONFIRM_KEY_GUARD_REQUEST)) {
            // will return password value via onActivityResult
            return;
        }
        finish();
    }

    /**
     * Returns true if the currently set key guard matches our minimum quality requirements.
     */
    private boolean checkKeyGuardQuality() {
        int credentialOwner =
                UserManager.get(this).getCredentialOwnerProfile(UserHandle.myUserId());
        int quality = new LockPatternUtils(this).getActivePasswordQuality(credentialOwner);
        return (quality >= MIN_PASSWORD_QUALITY);
    }

    private boolean isHardwareBackedKey(byte[] keyData) {
        try {
            ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
            PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
            String algOid = pki.getPrivateKeyAlgorithm().getAlgorithm().getId();
            String algName = new AlgorithmId(new ObjectIdentifier(algOid)).getName();

            return KeyChain.isBoundKeyAlgorithm(algName);
        } catch (IOException e) {
            Log.e(TAG, "Failed to parse key data");
            return false;
        }
    }

    /**
     * Install credentials if available, otherwise do nothing.
     */
    private void installIfAvailable() {
        if (mInstallBundle == null || mInstallBundle.isEmpty()) {
            return;
        }

        Bundle bundle = mInstallBundle;
        mInstallBundle = null;

        final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, KeyStore.UID_SELF);

        if (uid != KeyStore.UID_SELF && !UserHandle.isSameUser(uid, Process.myUid())) {
            int dstUserId = UserHandle.getUserId(uid);
            int myUserId = UserHandle.myUserId();

            // Restrict install target to the wifi uid.
            if (uid != Process.WIFI_UID) {
                Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs"
                        + " may only target wifi uids");
                return;
            }

            Intent installIntent = new Intent(ACTION_INSTALL)
                    .setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
                    .putExtras(bundle);
            startActivityAsUser(installIntent, new UserHandle(dstUserId));
            return;
        }

        if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) {
            String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
            byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);

            int flags = KeyStore.FLAG_ENCRYPTED;
            if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) {
                // Hardware backed keystore is secure enough to allow for WIFI stack
                // to enable access to secure networks without user intervention
                Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID");
                flags = KeyStore.FLAG_NONE;
            }

            if (!mKeyStore.importKey(key, value, uid, flags)) {
                Log.e(TAG, "Failed to install " + key + " as uid " + uid);
                return;
            }
            // The key was prepended USER_PRIVATE_KEY by the CredentialHelper. However,
            // KeyChain internally uses the raw alias name and only prepends USER_PRIVATE_KEY
            // to the key name when interfacing with KeyStore.
            // This is generally a symptom of CredentialStorage and CredentialHelper relying
            // on internal implementation details of KeyChain and imitating its functionality
            // rather than delegating to KeyChain for the certificate installation.
            if (uid == Process.SYSTEM_UID || uid == KeyStore.UID_SELF) {
                new MarkKeyAsUserSelectable(
                        key.replaceFirst("^" + Credentials.USER_PRIVATE_KEY, "")).execute();
            }
        }

        int flags = KeyStore.FLAG_NONE;

        if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
            String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
            byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);

            if (!mKeyStore.put(certName, certData, uid, flags)) {
                Log.e(TAG, "Failed to install " + certName + " as uid " + uid);
                return;
            }
        }

        if (bundle.containsKey(Credentials.EXTRA_CA_CERTIFICATES_NAME)) {
            String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
            byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA);

            if (!mKeyStore.put(caListName, caListData, uid, flags)) {
                Log.e(TAG, "Failed to install " + caListName + " as uid " + uid);
                return;
            }
        }

        // Send the broadcast.
        Intent broadcast = new Intent(KeyChain.ACTION_KEYCHAIN_CHANGED);
        sendBroadcast(broadcast);

        setResult(RESULT_OK);
    }

    /**
     * Prompt for reset confirmation, resetting on confirmation, finishing otherwise.
     */
    private class ResetDialog
            implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
        private boolean mResetConfirmed;

        private ResetDialog() {
            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
                    .setTitle(android.R.string.dialog_alert_title)
                    .setMessage(R.string.credentials_reset_hint)
                    .setPositiveButton(android.R.string.ok, this)
                    .setNegativeButton(android.R.string.cancel, this)
                    .create();
            dialog.setOnDismissListener(this);
            dialog.show();
        }

        @Override
        public void onClick(DialogInterface dialog, int button) {
            mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            if (mResetConfirmed) {
                mResetConfirmed = false;
                if (confirmKeyGuard(CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST)) {
                    // will return password value via onActivityResult
                    return;
                }
            }
            finish();
        }
    }

    /**
     * Background task to handle reset of both keystore and user installed CAs.
     */
    private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... unused) {

            // Clear all the users credentials could have been installed in for this user.
            new LockPatternUtils(CredentialStorage.this).resetKeyStore(UserHandle.myUserId());

            try {
                KeyChainConnection keyChainConnection = KeyChain.bind(CredentialStorage.this);
                try {
                    return keyChainConnection.getService().reset();
                } catch (RemoteException e) {
                    return false;
                } finally {
                    keyChainConnection.close();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean success) {
            if (success) {
                Toast.makeText(CredentialStorage.this,
                        R.string.credentials_erased, Toast.LENGTH_SHORT).show();
                clearLegacyVpnIfEstablished();
            } else {
                Toast.makeText(CredentialStorage.this,
                        R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
            }
            finish();
        }
    }

    private void clearLegacyVpnIfEstablished() {
        boolean isDone = VpnUtils.disconnectLegacyVpn(getApplicationContext());
        if (isDone) {
            Toast.makeText(CredentialStorage.this, R.string.vpn_disconnected,
                    Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * Background task to mark a given key alias as user-selectable, so that
     * it can be selected by users from the Certificate Selection prompt.
     */
    private class MarkKeyAsUserSelectable extends AsyncTask<Void, Void, Boolean> {
        final String mAlias;

        public MarkKeyAsUserSelectable(String alias) {
            mAlias = alias;
        }

        @Override
        protected Boolean doInBackground(Void... unused) {
            try (KeyChainConnection keyChainConnection = KeyChain.bind(CredentialStorage.this)) {
                keyChainConnection.getService().setUserSelectable(mAlias, true);
                return true;
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to mark key " + mAlias + " as user-selectable.");
                return false;
            } catch (InterruptedException e) {
                Log.w(TAG, "Failed to mark key " + mAlias + " as user-selectable.");
                Thread.currentThread().interrupt();
                return false;
            }
        }
    }

    /**
     * Check that the caller is either certinstaller or Settings running in a profile of this user.
     */
    private boolean checkCallerIsCertInstallerOrSelfInProfile() {
        if (TextUtils.equals("com.android.certinstaller", getCallingPackage())) {
            // CertInstaller is allowed to install credentials if it has the same signature as
            // Settings package.
            return getPackageManager().checkSignatures(
                    getCallingPackage(), getPackageName()) == PackageManager.SIGNATURE_MATCH;
        }

        final int launchedFromUserId;
        try {
            int launchedFromUid = android.app.ActivityManager.getService()
                    .getLaunchedFromUid(getActivityToken());
            if (launchedFromUid == -1) {
                Log.e(TAG, ACTION_INSTALL + " must be started with startActivityForResult");
                return false;
            }
            if (!UserHandle.isSameApp(launchedFromUid, Process.myUid())) {
                // Not the same app
                return false;
            }
            launchedFromUserId = UserHandle.getUserId(launchedFromUid);
        } catch (RemoteException re) {
            // Error talking to ActivityManager, just give up
            return false;
        }

        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
        UserInfo parentInfo = userManager.getProfileParent(launchedFromUserId);
        if (parentInfo == null || parentInfo.id != UserHandle.myUserId()) {
            // Caller is not running in a profile of this user
            return false;
        }
        return true;
    }

    /**
     * Confirm existing key guard, returning password via onActivityResult.
     */
    private boolean confirmKeyGuard(int requestCode) {
        Resources res = getResources();
        boolean launched = new ChooseLockSettingsHelper(this)
                .launchConfirmationActivity(requestCode,
                        res.getText(R.string.credentials_title), true);
        return launched;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        /**
         * Receive key guard password initiated by confirmKeyGuard.
         */
        if (requestCode == CONFIRM_KEY_GUARD_REQUEST) {
            if (resultCode == Activity.RESULT_OK) {
                String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
                if (!TextUtils.isEmpty(password)) {
                    // success
                    mKeyStore.unlock(password);
                    // return to onResume
                    return;
                }
            }
            // failed confirmation, bail
            finish();
        } else if (requestCode == CONFIRM_CLEAR_SYSTEM_CREDENTIAL_REQUEST) {
            if (resultCode == Activity.RESULT_OK) {
                new ResetKeyStoreAndKeyChain().execute();
                return;
            }
            // failed confirmation, bail
            finish();
        }
    }

    /**
     * Prompt for unlock with old-style password.
     *
     * On successful unlock, ensure migration to key guard before continuing.
     * On unsuccessful unlock, retry by calling handleUnlockOrInstall.
     */
    private class UnlockDialog implements TextWatcher,
            DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
        private boolean mUnlockConfirmed;

        private final Button mButton;
        private final TextView mOldPassword;
        private final TextView mError;

        private UnlockDialog() {
            View view = View.inflate(CredentialStorage.this, R.layout.credentials_dialog, null);

            CharSequence text;
            if (mRetriesRemaining == -1) {
                text = getResources().getText(R.string.credentials_unlock_hint);
            } else if (mRetriesRemaining > 3) {
                text = getResources().getText(R.string.credentials_wrong_password);
            } else if (mRetriesRemaining == 1) {
                text = getResources().getText(R.string.credentials_reset_warning);
            } else {
                text = getString(R.string.credentials_reset_warning_plural, mRetriesRemaining);
            }

            ((TextView) view.findViewById(R.id.hint)).setText(text);
            mOldPassword = (TextView) view.findViewById(R.id.old_password);
            mOldPassword.setVisibility(View.VISIBLE);
            mOldPassword.addTextChangedListener(this);
            mError = (TextView) view.findViewById(R.id.error);

            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
                    .setView(view)
                    .setTitle(R.string.credentials_unlock)
                    .setPositiveButton(android.R.string.ok, this)
                    .setNegativeButton(android.R.string.cancel, this)
                    .create();
            dialog.setOnDismissListener(this);
            dialog.show();
            mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
            mButton.setEnabled(false);
        }

        @Override
        public void afterTextChanged(Editable editable) {
            mButton.setEnabled(mOldPassword == null || mOldPassword.getText().length() > 0);
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void onClick(DialogInterface dialog, int button) {
            mUnlockConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            if (mUnlockConfirmed) {
                mUnlockConfirmed = false;
                mError.setVisibility(View.VISIBLE);
                mKeyStore.unlock(mOldPassword.getText().toString());
                int error = mKeyStore.getLastError();
                if (error == KeyStore.NO_ERROR) {
                    mRetriesRemaining = -1;
                    Toast.makeText(CredentialStorage.this,
                            R.string.credentials_enabled,
                            Toast.LENGTH_SHORT).show();
                    // aha, now we are unlocked, switch to key guard.
                    // we'll end up back in onResume to install
                    ensureKeyGuard();
                } else if (error == KeyStore.UNINITIALIZED) {
                    mRetriesRemaining = -1;
                    Toast.makeText(CredentialStorage.this,
                            R.string.credentials_erased,
                            Toast.LENGTH_SHORT).show();
                    // we are reset, we can now set new password with key guard
                    handleUnlockOrInstall();
                } else if (error >= KeyStore.WRONG_PASSWORD) {
                    // we need to try again
                    mRetriesRemaining = error - KeyStore.WRONG_PASSWORD + 1;
                    handleUnlockOrInstall();
                }
                return;
            }
            finish();
        }
    }
}
