From b46e493e2cd4f0ceffe90a0f9065f1990ba502cc Mon Sep 17 00:00:00 2001 From: Robin Lee Date: Tue, 3 Feb 2015 18:17:39 +0000 Subject: 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 --- src/com/android/keychain/KeyChainActivity.java | 68 +++++++++++++++++++++++--- 1 file 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 { @@ -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; -- cgit v1.2.3