/*
 * Copyright (C) 2009 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.certinstaller;

import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.security.Credentials;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Toast;

import java.io.Serializable;

/**
 * Installs certificates to the system keystore.
 */
public class CertInstaller extends Activity {
    private static final String TAG = "CertInstaller";

    private static final int STATE_INIT = 1;
    private static final int STATE_RUNNING = 2;
    private static final int STATE_PAUSED = 3;

    private static final int NAME_CREDENTIAL_DIALOG = 1;
    private static final int PKCS12_PASSWORD_DIALOG = 2;
    private static final int PROGRESS_BAR_DIALOG = 3;
    private static final int REDIRECT_CA_CERTIFICATE_DIALOG = 4;
    private static final int SELECT_CERTIFICATE_USAGE_DIALOG = 5;
    private static final int INVALID_CERTIFICATE_DIALOG = 6;

    private static final int REQUEST_SYSTEM_INSTALL_CODE = 1;

    // key to states Bundle
    private static final String NEXT_ACTION_KEY = "na";

    private final ViewHelper mView = new ViewHelper();

    private int mState;
    private CredentialHelper mCredentials;
    private MyAction mNextAction;

    private CredentialHelper createCredentialHelper(Intent intent) {
        try {
            return new CredentialHelper(intent);
        } catch (Throwable t) {
            Log.w(TAG, "createCredentialHelper", t);
            toastErrorAndFinish(R.string.invalid_cert);
            return new CredentialHelper();
        }
    }

    @Override
    protected void onCreate(Bundle savedStates) {
        super.onCreate(savedStates);
        getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);

        mCredentials = createCredentialHelper(getIntent());

        mState = (savedStates == null) ? STATE_INIT : STATE_RUNNING;

        if (mState == STATE_INIT) {
            if (!mCredentials.containsAnyRawData()) {
                toastErrorAndFinish(R.string.no_cert_to_saved);
                finish();
            } else {
                if (installingCaCertificate()) {
                    extractPkcs12OrInstall();
                } else {
                    if (mCredentials.hasUserCertificate() && !mCredentials.hasPrivateKey()) {
                        toastErrorAndFinish(R.string.action_missing_private_key);
                    } else if (mCredentials.hasPrivateKey() && !mCredentials.hasUserCertificate()) {
                        toastErrorAndFinish(R.string.action_missing_user_cert);
                    } else {
                        extractPkcs12OrInstall();
                    }
                }
            }
        } else {
            mCredentials.onRestoreStates(savedStates);
            mNextAction = (MyAction)
                    savedStates.getSerializable(NEXT_ACTION_KEY);
        }
    }

    private boolean installingCaCertificate() {
        return mCredentials.hasCaCerts() && !mCredentials.hasPrivateKey() &&
                !mCredentials.hasUserCertificate();
    }

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

        if (mState == STATE_INIT) {
            mState = STATE_RUNNING;
        } else {
            if (mNextAction != null) {
                mNextAction.run(this);
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        mState = STATE_PAUSED;
    }

    @Override
    protected void onSaveInstanceState(Bundle outStates) {
        super.onSaveInstanceState(outStates);
        mCredentials.onSaveStates(outStates);
        if (mNextAction != null) {
            outStates.putSerializable(NEXT_ACTION_KEY, mNextAction);
        }
    }

    @Override
    protected Dialog onCreateDialog (int dialogId) {
        switch (dialogId) {
            case PKCS12_PASSWORD_DIALOG:
                return createPkcs12PasswordDialog();

            case NAME_CREDENTIAL_DIALOG:
                return createNameCertificateDialog();

            case PROGRESS_BAR_DIALOG:
                ProgressDialog dialog = new ProgressDialog(this);
                dialog.setMessage(getString(R.string.extracting_pkcs12));
                dialog.setIndeterminate(true);
                dialog.setCancelable(false);
                return dialog;

            case REDIRECT_CA_CERTIFICATE_DIALOG:
                return createRedirectCaCertificateDialog();

            case SELECT_CERTIFICATE_USAGE_DIALOG:
                return createSelectCertificateUsageDialog();

            case INVALID_CERTIFICATE_DIALOG:
                return createInvalidCertificateDialog();

            default:
                return null;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_SYSTEM_INSTALL_CODE:
                if (resultCode != RESULT_OK) {
                    Log.d(TAG, "credential not saved, err: " + resultCode);
                    toastErrorAndFinish(R.string.cert_not_saved);
                    return;
                }

                Log.d(TAG, "credential is added: " + mCredentials.getName());
                if (mCredentials.getCertUsageSelected().equals(Credentials.CERTIFICATE_USAGE_WIFI)) {
                    Toast.makeText(this, R.string.wifi_cert_is_added, Toast.LENGTH_LONG).show();
                } else {
                    Toast.makeText(this, R.string.user_cert_is_added, Toast.LENGTH_LONG).show();
                }
                setResult(RESULT_OK);
                finish();
                break;
            default:
                Log.w(TAG, "unknown request code: " + requestCode);
                finish();
                break;
        }
    }

    private void extractPkcs12OrInstall() {
        if (mCredentials.hasPkcs12KeyStore()) {
            if (mCredentials.hasPassword()) {
                showDialog(PKCS12_PASSWORD_DIALOG);
            } else {
                new Pkcs12ExtractAction("").run(this);
            }
        } else {
            if (mCredentials.calledBySettings()) {
                MyAction action = new InstallOthersAction();
                action.run(this);
            } else {
                createRedirectOrSelectUsageDialog();
            }
        }
    }

    private class InstallVpnAndAppsTrustAnchorsTask extends AsyncTask<Void, Void, Boolean> {

        @Override
        protected Boolean doInBackground(Void... unused) {
            try {
                try (KeyChainConnection keyChainConnection = KeyChain.bind(CertInstaller.this)) {
                    return mCredentials.installVpnAndAppsTrustAnchors(CertInstaller.this,
                            keyChainConnection.getService());
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }

        @Override
        protected void onPostExecute(Boolean success) {
            if (success) {
                Toast.makeText(getApplicationContext(), R.string.ca_cert_is_added,
                        Toast.LENGTH_LONG).show();
                setResult(RESULT_OK);
            }
            finish();
        }
    }

    private void installOthers() {
        // Sanity check: Check that there's either:
        // * A private key AND a user certificate, or
        // * A CA cert.
        boolean hasPrivateKeyAndUserCertificate =
                mCredentials.hasPrivateKey() && mCredentials.hasUserCertificate();
        boolean hasCaCertificate = mCredentials.hasCaCerts();
        Log.d(TAG,
                String.format(
                        "Attempting credentials installation, has ca cert? %b, has user cert? %b",
                        hasCaCertificate, hasPrivateKeyAndUserCertificate));
        if (!(hasPrivateKeyAndUserCertificate || hasCaCertificate)) {
            finish();
            return;
        }

        if (validCertificateSelected()) {
            installCertificateOrShowNameDialog();
        } else {
            showDialog(INVALID_CERTIFICATE_DIALOG);
        }
    }

    private boolean validCertificateSelected() {
        switch (mCredentials.getCertUsageSelected()) {
            case Credentials.CERTIFICATE_USAGE_CA:
                return mCredentials.hasOnlyVpnAndAppsTrustAnchors();
            case Credentials.CERTIFICATE_USAGE_USER:
                return mCredentials.hasUserCertificate()
                        && !mCredentials.hasOnlyVpnAndAppsTrustAnchors();
            case Credentials.CERTIFICATE_USAGE_WIFI:
                return true;
            default:
                return false;
        }
    }

    private void installCertificateOrShowNameDialog() {
        if (!mCredentials.hasAnyForSystemInstall()) {
            toastErrorAndFinish(R.string.no_cert_to_saved);
        } else if (mCredentials.hasOnlyVpnAndAppsTrustAnchors()) {
            // If there's only a CA certificate to install, then it's going to be used
            // as a trust anchor. Install it and skip importing to Keystore.

            // more work to do, don't finish just yet
            new InstallVpnAndAppsTrustAnchorsTask().execute();
        } else {
            // Name is required if installing User certificate
            showDialog(NAME_CREDENTIAL_DIALOG);
        }
    }

    private void extractPkcs12InBackground(final String password) {
        // show progress bar and extract certs in a background thread
        showDialog(PROGRESS_BAR_DIALOG);

        new AsyncTask<Void,Void,Boolean>() {
            @Override protected Boolean doInBackground(Void... unused) {
                return mCredentials.extractPkcs12(password);
            }
            @Override protected void onPostExecute(Boolean success) {
                MyAction action = new OnExtractionDoneAction(success);
                if (mState == STATE_PAUSED) {
                    // activity is paused; run it in next onResume()
                    mNextAction = action;
                } else {
                    action.run(CertInstaller.this);
                }
            }
        }.execute();
    }

    private void onExtractionDone(boolean success) {
        mNextAction = null;
        removeDialog(PROGRESS_BAR_DIALOG);
        if (success) {
            removeDialog(PKCS12_PASSWORD_DIALOG);
            if (mCredentials.calledBySettings()) {
                if (validCertificateSelected()) {
                    installCertificateOrShowNameDialog();
                } else {
                    showDialog(INVALID_CERTIFICATE_DIALOG);
                }
            } else {
                createRedirectOrSelectUsageDialog();
            }
        } else {
            showDialog(PKCS12_PASSWORD_DIALOG);
            mView.setText(R.id.credential_password, "");
            mView.showError(R.string.password_error);
        }
    }

    private void createRedirectOrSelectUsageDialog() {
        if (mCredentials.hasOnlyVpnAndAppsTrustAnchors()) {
            showDialog(REDIRECT_CA_CERTIFICATE_DIALOG);
        } else {
            showDialog(SELECT_CERTIFICATE_USAGE_DIALOG);
        }
    }

    private Dialog createRedirectCaCertificateDialog() {
        Dialog d = new AlertDialog.Builder(this)
                .setTitle(R.string.redirect_ca_certificate_title)
                .setMessage(R.string.redirect_ca_certificate_message)
                .setPositiveButton(R.string.redirect_ca_certificate_close_button,
                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
                .create();
        d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved));
        return d;
    }

    private Dialog createSelectCertificateUsageDialog() {
        ViewGroup view = (ViewGroup) View.inflate(this, R.layout.select_certificate_usage_dialog,
                null);
        mView.setView(view);

        RadioGroup radioGroup = view.findViewById(R.id.certificate_usage);
        radioGroup.setOnCheckedChangeListener((group, checkedId) -> {
            switch (checkedId) {
                case R.id.user_certificate:
                    mCredentials.setCertUsageSelected(Credentials.CERTIFICATE_USAGE_USER);
                    break;
                case R.id.wifi_certificate:
                    mCredentials.setCertUsageSelected(Credentials.CERTIFICATE_USAGE_WIFI);
                default:
                    Slog.i(TAG, "Unknown selection for scope");
            }
        });


        final Context appContext = getApplicationContext();
        Dialog d = new AlertDialog.Builder(this)
                .setView(view)
                .setPositiveButton(android.R.string.ok, (dialog, id) -> {
                    if (radioGroup.getCheckedRadioButtonId() == R.id.user_certificate) {
                        showDialog(NAME_CREDENTIAL_DIALOG);
                    } else {
                        installCertificateToKeystore(appContext);
                    }
                })
                .setNegativeButton(android.R.string.cancel,
                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
                .create();
        d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved));
        return d;
    }

    private Dialog createInvalidCertificateDialog() {
        Dialog d = new AlertDialog.Builder(this)
                .setTitle(R.string.invalid_certificate_title)
                .setMessage(getString(R.string.invalid_certificate_message,
                        getCertificateUsageName()))
                .setPositiveButton(R.string.invalid_certificate_close_button,
                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
                .create();
        d.setOnCancelListener(dialog -> finish());
        return d;
    }

    String getCertificateUsageName() {
        switch (mCredentials.getCertUsageSelected()) {
            case Credentials.CERTIFICATE_USAGE_CA:
                return getString(R.string.ca_certificate);
            case Credentials.CERTIFICATE_USAGE_USER:
                return getString(R.string.user_certificate);
            case Credentials.CERTIFICATE_USAGE_WIFI:
                return getString(R.string.wifi_certificate);
            default:
                return getString(R.string.certificate);
        }
    }

    private Dialog createPkcs12PasswordDialog() {
        View view = View.inflate(this, R.layout.password_dialog, null);
        mView.setView(view);
        if (mView.getHasEmptyError()) {
            mView.showError(R.string.password_empty_error);
            mView.setHasEmptyError(false);
        }

        String title = mCredentials.getName();
        title = TextUtils.isEmpty(title)
                ? getString(R.string.pkcs12_password_dialog_title)
                : getString(R.string.pkcs12_file_password_dialog_title, title);
        Dialog d = new AlertDialog.Builder(this)
                .setView(view)
                .setTitle(title)
                .setPositiveButton(android.R.string.ok, (dialog, id) -> {
                    String password = mView.getText(R.id.credential_password);
                    mNextAction = new Pkcs12ExtractAction(password);
                    mNextAction.run(CertInstaller.this);
                 })
                .setNegativeButton(android.R.string.cancel,
                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
                .create();
        d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved));
        return d;
    }

    private Dialog createNameCertificateDialog() {
        ViewGroup view = (ViewGroup) View.inflate(this, R.layout.name_certificate_dialog, null);
        mView.setView(view);
        if (mView.getHasEmptyError()) {
            mView.showError(R.string.name_empty_error);
            mView.setHasEmptyError(false);
        }
        final EditText nameInput = view.findViewById(R.id.certificate_name);
        nameInput.setText(getDefaultName());
        nameInput.selectAll();
        final Context appContext = getApplicationContext();

        Dialog d = new AlertDialog.Builder(this)
                .setView(view)
                .setTitle(R.string.name_credential_dialog_title)
                .setPositiveButton(android.R.string.ok, (dialog, id) -> {
                    String name = mView.getText(R.id.certificate_name);
                    if (TextUtils.isEmpty(name)) {
                        mView.setHasEmptyError(true);
                        removeDialog(NAME_CREDENTIAL_DIALOG);
                        showDialog(NAME_CREDENTIAL_DIALOG);
                    } else {
                        removeDialog(NAME_CREDENTIAL_DIALOG);
                        mCredentials.setName(name);
                        installCertificateToKeystore(appContext);
                    }
                })
                .setNegativeButton(android.R.string.cancel,
                        (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved))
                .create();
        d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved));
        return d;
    }

    private void installCertificateToKeystore(Context context) {
        try {
            startActivityForResult(
                    mCredentials.createSystemInstallIntent(context),
                    REQUEST_SYSTEM_INSTALL_CODE);
        } catch (ActivityNotFoundException e) {
            Log.w(TAG, "installCertificateToKeystore(): ", e);
            toastErrorAndFinish(R.string.cert_not_saved);
        }
    }

    private String getDefaultName() {
        String name = mCredentials.getName();
        if (TextUtils.isEmpty(name)) {
            return null;
        } else {
            // remove the extension from the file name
            int index = name.lastIndexOf(".");
            if (index > 0) name = name.substring(0, index);
            return name;
        }
    }

    private void toastErrorAndFinish(int msgId) {
        Toast.makeText(this, msgId, Toast.LENGTH_SHORT).show();
        finish();
    }

    private interface MyAction extends Serializable {
        void run(CertInstaller host);
    }

    private static class Pkcs12ExtractAction implements MyAction {
        private final String mPassword;
        private transient boolean hasRun;

        Pkcs12ExtractAction(String password) {
            mPassword = password;
        }

        public void run(CertInstaller host) {
            if (hasRun) {
                return;
            }
            hasRun = true;
            host.extractPkcs12InBackground(mPassword);
        }
    }

    private static class InstallOthersAction implements MyAction {
        public void run(CertInstaller host) {
            host.mNextAction = null;
            host.installOthers();
        }
    }

    private static class OnExtractionDoneAction implements MyAction {
        private final boolean mSuccess;

        OnExtractionDoneAction(boolean success) {
            mSuccess = success;
        }

        public void run(CertInstaller host) {
            host.onExtractionDone(mSuccess);
        }
    }
}
