diff options
author | Pavel Grafov <pgrafov@google.com> | 2019-05-31 04:17:20 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-05-31 04:17:20 -0700 |
commit | e23dfe2f2eaad8b835236e6561de6ab6116ce049 (patch) | |
tree | b20494556563f4141898eaa2be174a860b751975 | |
parent | d6bc1479a3d9fdf40eab1a596961d08cd5b89634 (diff) | |
parent | 7f7d5aa9d39af1fd5149302327a16556ce0028b0 (diff) | |
download | CertInstaller-e23dfe2f2eaad8b835236e6561de6ab6116ce049.tar.gz |
Confirm user credentials before installing CA.
am: 7f7d5aa9d3
Change-Id: Id74e28980a3fe12b63bfa3000fd89d4a5846f42f
-rw-r--r-- | src/com/android/certinstaller/CertInstaller.java | 172 | ||||
-rw-r--r-- | src/com/android/certinstaller/CredentialHelper.java | 23 |
2 files changed, 89 insertions, 106 deletions
diff --git a/src/com/android/certinstaller/CertInstaller.java b/src/com/android/certinstaller/CertInstaller.java index faa2f5a..31f5fd3 100644 --- a/src/com/android/certinstaller/CertInstaller.java +++ b/src/com/android/certinstaller/CertInstaller.java @@ -23,12 +23,10 @@ import android.app.KeyguardManager; import android.app.ProgressDialog; import android.content.ActivityNotFoundException; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.os.Process; -import android.security.Credentials; import android.security.KeyChain; import android.security.KeyChain.KeyChainConnection; import android.security.KeyStore; @@ -43,9 +41,6 @@ import android.widget.Spinner; import android.widget.Toast; import java.io.Serializable; -import java.security.cert.X509Certificate; -import java.util.LinkedHashMap; -import java.util.Map; /** * Installs certificates to the system keystore. @@ -62,13 +57,11 @@ public class CertInstaller extends Activity { private static final int PROGRESS_BAR_DIALOG = 3; private static final int REQUEST_SYSTEM_INSTALL_CODE = 1; + private static final int REQUEST_CONFIRM_CREDENTIALS = 2; // key to states Bundle private static final String NEXT_ACTION_KEY = "na"; - // key to KeyStore - private static final String PKEY_MAP_KEY = "PKEY_MAP"; - // Values for usage type spinner private static final int USAGE_TYPE_SYSTEM = 0; private static final int USAGE_TYPE_WIFI = 1; @@ -103,7 +96,14 @@ public class CertInstaller extends Activity { finish(); } else { if (mCredentials.hasCaCerts()) { - extractPkcs12OrInstall(); + KeyguardManager keyguardManager = getSystemService(KeyguardManager.class); + Intent intent = keyguardManager.createConfirmDeviceCredentialIntent(null, null); + if (intent == null) { // No screenlock + extractPkcs12OrInstall(); + } else { + // TODO(b/134057817): only do it when installing CA cert as a trust anchor. + startActivityForResult(intent, REQUEST_CONFIRM_CREDENTIALS); + } } else { if (mCredentials.hasUserCertificate() && !mCredentials.hasPrivateKey()) { toastErrorAndFinish(R.string.action_missing_private_key); @@ -172,29 +172,39 @@ public class CertInstaller extends Activity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode != REQUEST_SYSTEM_INSTALL_CODE) { - Log.w(TAG, "unknown request code: " + requestCode); - finish(); - return; - } - - if (resultCode != RESULT_OK) { - Log.d(TAG, "credential not saved, err: " + resultCode); - toastErrorAndFinish(R.string.cert_not_saved); - return; - } + 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()); - Toast.makeText(this, getString(R.string.cert_is_added, mCredentials.getName()), - Toast.LENGTH_LONG).show(); + Log.d(TAG, "credential is added: " + mCredentials.getName()); + Toast.makeText(this, getString(R.string.cert_is_added, mCredentials.getName()), + Toast.LENGTH_LONG).show(); - if (mCredentials.includesVpnAndAppsTrustAnchors()) { - // more work to do, don't finish just yet - new InstallVpnAndAppsTrustAnchorsTask().execute(); - return; + if (mCredentials.includesVpnAndAppsTrustAnchors()) { + // more work to do, don't finish just yet + new InstallVpnAndAppsTrustAnchorsTask().execute(); + return; + } + setResult(RESULT_OK); + finish(); + break; + case REQUEST_CONFIRM_CREDENTIALS: + if (resultCode == RESULT_OK) { + extractPkcs12OrInstall(); + return; + } + // Failed to confirm credentials, do nothing. + finish(); + break; + default: + Log.w(TAG, "unknown request code: " + requestCode); + finish(); + break; } - setResult(RESULT_OK); - finish(); } private void extractPkcs12OrInstall() { @@ -214,12 +224,9 @@ public class CertInstaller extends Activity { @Override protected Boolean doInBackground(Void... unused) { try { - KeyChainConnection keyChainConnection = KeyChain.bind(CertInstaller.this); - try { + try (KeyChainConnection keyChainConnection = KeyChain.bind(CertInstaller.this)) { return mCredentials.installVpnAndAppsTrustAnchors(CertInstaller.this, keyChainConnection.getService()); - } finally { - keyChainConnection.close(); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); @@ -235,7 +242,7 @@ public class CertInstaller extends Activity { } } - void installOthers() { + private void installOthers() { // Sanity check: Check that there's either: // * A private key AND a user certificate, or // * A CA cert. @@ -262,7 +269,7 @@ public class CertInstaller extends Activity { } } - void extractPkcs12InBackground(final String password) { + private void extractPkcs12InBackground(final String password) { // show progress bar and extract certs in a background thread showDialog(PROGRESS_BAR_DIALOG); @@ -282,7 +289,7 @@ public class CertInstaller extends Activity { }.execute(); } - void onExtractionDone(boolean success) { + private void onExtractionDone(boolean success) { mNextAction = null; removeDialog(PROGRESS_BAR_DIALOG); if (success) { @@ -310,24 +317,15 @@ public class CertInstaller extends Activity { Dialog d = new AlertDialog.Builder(this) .setView(view) .setTitle(title) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - String password = mView.getText(R.id.credential_password); - mNextAction = new Pkcs12ExtractAction(password); - mNextAction.run(CertInstaller.this); - } - }) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - toastErrorAndFinish(R.string.cert_not_saved); - } - }) + .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(new DialogInterface.OnCancelListener() { - @Override public void onCancel(DialogInterface dialog) { - toastErrorAndFinish(R.string.cert_not_saved); - } - }); + d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved)); return d; } @@ -339,11 +337,11 @@ public class CertInstaller extends Activity { mView.setHasEmptyError(false); } mView.setText(R.id.credential_info, mCredentials.getDescription(this).toString()); - final EditText nameInput = (EditText) view.findViewById(R.id.credential_name); + final EditText nameInput = view.findViewById(R.id.credential_name); if (mCredentials.isInstallAsUidSet()) { view.findViewById(R.id.credential_usage_group).setVisibility(View.GONE); } else { - final Spinner usageSpinner = (Spinner) view.findViewById(R.id.credential_usage); + final Spinner usageSpinner = view.findViewById(R.id.credential_usage); final View ca_capabilities_warning = view.findViewById(R.id.credential_capabilities_warning); usageSpinner.setOnItemSelectedListener(new OnItemSelectedListener() { @@ -376,40 +374,31 @@ public class CertInstaller extends Activity { Dialog d = new AlertDialog.Builder(this) .setView(view) .setTitle(R.string.name_credential_dialog_title) - .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - String name = mView.getText(R.id.credential_name); - if (TextUtils.isEmpty(name)) { - mView.setHasEmptyError(true); - removeDialog(NAME_CREDENTIAL_DIALOG); - showDialog(NAME_CREDENTIAL_DIALOG); - } else { - removeDialog(NAME_CREDENTIAL_DIALOG); - mCredentials.setName(name); - - // install everything to system keystore - try { - startActivityForResult( - mCredentials.createSystemInstallIntent(appContext), - REQUEST_SYSTEM_INSTALL_CODE); - } catch (ActivityNotFoundException e) { - Log.w(TAG, "systemInstall(): " + e); - toastErrorAndFinish(R.string.cert_not_saved); - } + .setPositiveButton(android.R.string.ok, (dialog, id) -> { + String name = mView.getText(R.id.credential_name); + if (TextUtils.isEmpty(name)) { + mView.setHasEmptyError(true); + removeDialog(NAME_CREDENTIAL_DIALOG); + showDialog(NAME_CREDENTIAL_DIALOG); + } else { + removeDialog(NAME_CREDENTIAL_DIALOG); + mCredentials.setName(name); + + // install everything to system keystore + try { + startActivityForResult( + mCredentials.createSystemInstallIntent(appContext), + REQUEST_SYSTEM_INSTALL_CODE); + } catch (ActivityNotFoundException e) { + Log.w(TAG, "systemInstall(): " + e); + toastErrorAndFinish(R.string.cert_not_saved); } } }) - .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - toastErrorAndFinish(R.string.cert_not_saved); - } - }) + .setNegativeButton(android.R.string.cancel, + (dialog, id) -> toastErrorAndFinish(R.string.cert_not_saved)) .create(); - d.setOnCancelListener(new DialogInterface.OnCancelListener() { - @Override public void onCancel(DialogInterface dialog) { - toastErrorAndFinish(R.string.cert_not_saved); - } - }); + d.setOnCancelListener(dialog -> toastErrorAndFinish(R.string.cert_not_saved)); return d; } @@ -430,19 +419,6 @@ public class CertInstaller extends Activity { finish(); } - private static class MyMap extends LinkedHashMap<String, byte[]> - implements Serializable { - private static final long serialVersionUID = 1L; - - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - // Note: one key takes about 1300 bytes in the keystore, so be - // cautious about allowing more outstanding keys in the map that - // may go beyond keystore's max length for one entry. - return (size() > 3); - } - } - private interface MyAction extends Serializable { void run(CertInstaller host); } diff --git a/src/com/android/certinstaller/CredentialHelper.java b/src/com/android/certinstaller/CredentialHelper.java index 72219c8..2091226 100644 --- a/src/com/android/certinstaller/CredentialHelper.java +++ b/src/com/android/certinstaller/CredentialHelper.java @@ -16,6 +16,7 @@ package com.android.certinstaller; +import android.app.KeyguardManager; import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.Intent; @@ -310,7 +311,6 @@ class CredentialHelper { boolean installVpnAndAppsTrustAnchors(Context context, IKeyChainService keyChainService) { final TrustedCertificateStore trustedCertificateStore = new TrustedCertificateStore(); - final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); for (X509Certificate caCert : mCaCerts) { byte[] bytes = null; try { @@ -332,18 +332,25 @@ class CredentialHelper { return false; } - // Some CTS verifier test asks testers to reset auto approved CA cert by removing - // lock sreen, but it's not possible if we don't have Android lock screen. (e.g. - // Android is running in the container). In this case, disable auto cert approval. - if (context.getResources().getBoolean(R.bool.config_auto_cert_approval)) { - // Since the cert is installed by real user, the cert is approved by the user - dpm.approveCaCert(alias, UserHandle.myUserId(), true); - } + maybeApproveCaCert(context, alias); } } return true; } + private void maybeApproveCaCert(Context context, String alias) { + // Some CTS verifier test asks testers to reset auto approved CA cert by removing + // lock sreen, but it's not possible if we don't have Android lock screen. (e.g. + // Android is running in the container). In this case, disable auto cert approval. + final KeyguardManager keyguardManager = context.getSystemService(KeyguardManager.class); + if (keyguardManager.isDeviceSecure(UserHandle.myUserId()) + && context.getResources().getBoolean(R.bool.config_auto_cert_approval)) { + // Since the cert is installed by real user, the cert is approved by the user + final DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class); + dpm.approveCaCert(alias, UserHandle.myUserId(), true); + } + } + boolean hasPassword() { if (!hasPkcs12KeyStore()) { return false; |