summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobin Lee <rgl@google.com>2015-02-03 18:17:39 +0000
committerRobin Lee <rgl@google.com>2015-02-04 12:24:05 +0000
commitb46e493e2cd4f0ceffe90a0f9065f1990ba502cc (patch)
tree9ec7a232023029bfaac46d961a88603c3e7d26d7
parent8c5adfcd9ba2b2f491c5fe5b03e3258e0ac12564 (diff)
downloadandroid_packages_apps_KeyChain-b46e493e2cd4f0ceffe90a0f9065f1990ba502cc.tar.gz
android_packages_apps_KeyChain-b46e493e2cd4f0ceffe90a0f9065f1990ba502cc.tar.bz2
android_packages_apps_KeyChain-b46e493e2cd4f0ceffe90a0f9065f1990ba502cc.zip
Use device policy suggestions when choosing alias
Query device policy for a suggested certificate before showing any kind of selection UI. The RPC call is made at the same time as retrieving and listing certificates so performance impact should be relatively small. Bug: 15065444 Change-Id: I0729b435c218b7991e6cb5faedefb7900577afcc
-rw-r--r--src/com/android/keychain/KeyChainActivity.java68
1 files changed, 61 insertions, 7 deletions
diff --git a/src/com/android/keychain/KeyChainActivity.java b/src/com/android/keychain/KeyChainActivity.java
index 23aa1a1..6b876c4 100644
--- a/src/com/android/keychain/KeyChainActivity.java
+++ b/src/com/android/keychain/KeyChainActivity.java
@@ -17,15 +17,20 @@
package com.android.keychain;
import android.app.Activity;
+import android.app.admin.IDevicePolicyManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.PendingIntent;
+import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
import android.security.Credentials;
import android.security.IKeyChainAliasCallback;
import android.security.KeyChain;
@@ -49,6 +54,7 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.concurrent.ExecutionException;
import java.util.List;
import javax.security.auth.x500.X500Principal;
@@ -118,7 +124,7 @@ public class KeyChainActivity extends Activity {
// onActivityResult is called with REQUEST_UNLOCK
return;
}
- showCertChooserDialog();
+ chooseCertificate();
return;
case UNLOCK_REQUESTED:
// we've already asked, but have not heard back, probably just rotated.
@@ -134,8 +140,59 @@ public class KeyChainActivity extends Activity {
}
}
- private void showCertChooserDialog() {
- new AliasLoader().execute();
+ private void chooseCertificate() {
+ // Start loading the set of certs to choose from now- if device policy doesn't return an
+ // alias, having aliases loading already will save some time waiting for UI to start.
+ final AliasLoader loader = new AliasLoader();
+ loader.execute();
+
+ final IKeyChainAliasCallback.Stub callback = new IKeyChainAliasCallback.Stub() {
+ @Override public void alias(String alias) {
+ // Use policy-suggested alias if provided
+ if (alias != null) {
+ finish(alias);
+ return;
+ }
+
+ // No suggested alias - instead finish loading and show UI to pick one
+ final CertificateAdapter certAdapter;
+ try {
+ certAdapter = loader.get();
+ } catch (InterruptedException | ExecutionException e) {
+ Log.e(TAG, "Loading certificate aliases interrupted", e);
+ finish(null);
+ return;
+ }
+ runOnUiThread(new Runnable() {
+ @Override public void run() {
+ displayCertChooserDialog(certAdapter);
+ }
+ });
+ }
+ };
+
+ // Give a profile or device owner the chance to intercept the request, if a private key
+ // access listener is registered with the DevicePolicyManagerService.
+ IDevicePolicyManager devicePolicyManager = IDevicePolicyManager.Stub.asInterface(
+ ServiceManager.getService(Context.DEVICE_POLICY_SERVICE));
+
+ String host = getIntent().getStringExtra(KeyChain.EXTRA_HOST);
+ int port = getIntent().getIntExtra(KeyChain.EXTRA_PORT, -1);
+ String url = getIntent().getStringExtra(KeyChain.EXTRA_URL);
+ String alias = getIntent().getStringExtra(KeyChain.EXTRA_ALIAS);
+
+ try {
+ devicePolicyManager.choosePrivateKeyAlias(host, port, url, alias, callback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not bind to DevicePolicyManagerService", e);
+
+ // Proceed without a suggested alias.
+ try {
+ callback.alias(null);
+ } catch (RemoteException shouldNeverHappen) {
+ finish(null);
+ }
+ }
}
private class AliasLoader extends AsyncTask<Void, Void, CertificateAdapter> {
@@ -147,9 +204,6 @@ public class KeyChainActivity extends Activity {
Collections.sort(aliasList);
return new CertificateAdapter(aliasList);
}
- @Override protected void onPostExecute(CertificateAdapter adapter) {
- displayCertChooserDialog(adapter);
- }
}
private void displayCertChooserDialog(final CertificateAdapter adapter) {
@@ -363,7 +417,7 @@ public class KeyChainActivity extends Activity {
case REQUEST_UNLOCK:
if (mKeyStore.isUnlocked()) {
mState = State.INITIAL;
- showCertChooserDialog();
+ chooseCertificate();
} else {
// user must have canceled unlock, give up
mState = State.UNLOCK_CANCELED;