summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Grafov <pgrafov@google.com>2019-05-31 04:17:20 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-05-31 04:17:20 -0700
commite23dfe2f2eaad8b835236e6561de6ab6116ce049 (patch)
treeb20494556563f4141898eaa2be174a860b751975
parentd6bc1479a3d9fdf40eab1a596961d08cd5b89634 (diff)
parent7f7d5aa9d39af1fd5149302327a16556ce0028b0 (diff)
downloadCertInstaller-e23dfe2f2eaad8b835236e6561de6ab6116ce049.tar.gz
Confirm user credentials before installing CA.
am: 7f7d5aa9d3 Change-Id: Id74e28980a3fe12b63bfa3000fd89d4a5846f42f
-rw-r--r--src/com/android/certinstaller/CertInstaller.java172
-rw-r--r--src/com/android/certinstaller/CredentialHelper.java23
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;