diff options
author | Robin Lee <rgl@google.com> | 2014-11-14 11:26:38 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2014-11-14 11:26:39 +0000 |
commit | e464d9b9ee133d366bec1b6c879889572c9996d8 (patch) | |
tree | c9c2112d7d804b9da54b03094daa243912b61b8c /src/com | |
parent | 26104298eb53d2dfa693eec32934f9ac0aa3d525 (diff) | |
parent | 8823c3eda28930bcd6c8242bfed15b098d63acd0 (diff) | |
download | packages_apps_Settings-e464d9b9ee133d366bec1b6c879889572c9996d8.tar.gz packages_apps_Settings-e464d9b9ee133d366bec1b6c879889572c9996d8.tar.bz2 packages_apps_Settings-e464d9b9ee133d366bec1b6c879889572c9996d8.zip |
Merge "Forward wifi cert install intents to primary user" into lmp-mr1-dev
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/settings/CredentialStorage.java | 135 |
1 files changed, 96 insertions, 39 deletions
diff --git a/src/com/android/settings/CredentialStorage.java b/src/com/android/settings/CredentialStorage.java index 2e917f566..40bed9092 100644 --- a/src/com/android/settings/CredentialStorage.java +++ b/src/com/android/settings/CredentialStorage.java @@ -22,11 +22,13 @@ import android.app.admin.DevicePolicyManager; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.UserInfo; import android.content.res.Resources; import android.os.AsyncTask; import android.os.Bundle; import android.os.RemoteException; import android.os.Process; +import android.os.UserHandle; import android.os.UserManager; import android.security.Credentials; import android.security.KeyChain.KeyChainConnection; @@ -126,8 +128,7 @@ public final class CredentialStorage extends Activity { if (ACTION_RESET.equals(action)) { new ResetDialog(); } else { - if (ACTION_INSTALL.equals(action) - && "com.android.certinstaller".equals(getCallingPackage())) { + if (ACTION_INSTALL.equals(action) && checkCallerIsCertInstallerOrSelfInProfile()) { mInstallBundle = intent.getExtras(); } // ACTION_UNLOCK also handled here in addition to ACTION_INSTALL @@ -215,54 +216,74 @@ public final class CredentialStorage extends Activity { * Install credentials if available, otherwise do nothing. */ private void installIfAvailable() { - if (mInstallBundle != null && !mInstallBundle.isEmpty()) { - Bundle bundle = mInstallBundle; - mInstallBundle = null; - - final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1); - - if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) { - String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME); - byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA); - - int flags = KeyStore.FLAG_ENCRYPTED; - if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) { - // Hardware backed keystore is secure enough to allow for WIFI stack - // to enable access to secure networks without user intervention - Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID"); - flags = KeyStore.FLAG_NONE; - } + if (mInstallBundle == null || mInstallBundle.isEmpty()) { + return; + } - if (!mKeyStore.importKey(key, value, uid, flags)) { - Log.e(TAG, "Failed to install " + key + " as user " + uid); - return; - } + Bundle bundle = mInstallBundle; + mInstallBundle = null; + + final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, -1); + + if (!UserHandle.isSameUser(uid, Process.myUid())) { + int dstUserId = UserHandle.getUserId(uid); + int myUserId = UserHandle.myUserId(); + + // Restrict install target to the wifi uid. + if (uid != Process.WIFI_UID) { + Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs" + + " may only target wifi uids"); + return; } - int flags = (uid == Process.WIFI_UID) ? KeyStore.FLAG_NONE : KeyStore.FLAG_ENCRYPTED; + Intent installIntent = new Intent(ACTION_INSTALL) + .setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) + .putExtras(bundle); + startActivityAsUser(installIntent, new UserHandle(dstUserId)); + return; + } + + if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) { + String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME); + byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA); - if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) { - String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME); - byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA); + int flags = KeyStore.FLAG_ENCRYPTED; + if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) { + // Hardware backed keystore is secure enough to allow for WIFI stack + // to enable access to secure networks without user intervention + Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID"); + flags = KeyStore.FLAG_NONE; + } - if (!mKeyStore.put(certName, certData, uid, flags)) { - Log.e(TAG, "Failed to install " + certName + " as user " + uid); - return; - } + if (!mKeyStore.importKey(key, value, uid, flags)) { + Log.e(TAG, "Failed to install " + key + " as uid " + uid); + return; } + } - if (bundle.containsKey(Credentials.EXTRA_CA_CERTIFICATES_NAME)) { - String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME); - byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA); + int flags = (uid == Process.WIFI_UID) ? KeyStore.FLAG_NONE : KeyStore.FLAG_ENCRYPTED; - if (!mKeyStore.put(caListName, caListData, uid, flags)) { - Log.e(TAG, "Failed to install " + caListName + " as user " + uid); - return; - } + if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) { + String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME); + byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA); + + if (!mKeyStore.put(certName, certData, uid, flags)) { + Log.e(TAG, "Failed to install " + certName + " as uid " + uid); + return; } + } - setResult(RESULT_OK); + if (bundle.containsKey(Credentials.EXTRA_CA_CERTIFICATES_NAME)) { + String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME); + byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA); + + if (!mKeyStore.put(caListName, caListData, uid, flags)) { + Log.e(TAG, "Failed to install " + caListName + " as uid " + uid); + return; + } } + + setResult(RESULT_OK); } /** @@ -371,6 +392,42 @@ public final class CredentialStorage extends Activity { } /** + * Check that the caller is either certinstaller or Settings running in a profile of this user. + */ + private boolean checkCallerIsCertInstallerOrSelfInProfile() { + if (TextUtils.equals("com.android.certinstaller", getCallingPackage())) { + // CertInstaller is allowed to install credentials + return true; + } + + final int launchedFromUserId; + try { + int launchedFromUid = android.app.ActivityManagerNative.getDefault() + .getLaunchedFromUid(getActivityToken()); + if (launchedFromUid == -1) { + Log.e(TAG, ACTION_INSTALL + " must be started with startActivityForResult"); + return false; + } + if (!UserHandle.isSameApp(launchedFromUid, Process.myUid())) { + // Not the same app + return false; + } + launchedFromUserId = UserHandle.getUserId(launchedFromUid); + } catch (RemoteException re) { + // Error talking to ActivityManager, just give up + return false; + } + + UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); + UserInfo parentInfo = userManager.getProfileParent(launchedFromUserId); + if (parentInfo == null || parentInfo.id != UserHandle.myUserId()) { + // Caller is not running in a profile of this user + return false; + } + return true; + } + + /** * Confirm existing key guard, returning password via onActivityResult. */ private boolean confirmKeyGuard() { |