diff options
| author | Robin Lee <rgl@google.com> | 2014-08-13 09:50:25 +0100 |
|---|---|---|
| committer | Robin Lee <rgl@google.com> | 2014-08-29 23:03:42 +0100 |
| commit | f0246a8a14d69680d1776620e75a485cf963e574 (patch) | |
| tree | 7fffafa3844a193de4b206605bdb59599a0318d5 | |
| parent | d627eac286e377aec5c8f66d4746850c3eff8ff8 (diff) | |
| download | frameworks_base-f0246a8a14d69680d1776620e75a485cf963e574.zip frameworks_base-f0246a8a14d69680d1776620e75a485cf963e574.tar.gz frameworks_base-f0246a8a14d69680d1776620e75a485cf963e574.tar.bz2 | |
Keep managed profile keystores in sync with owner
Fixes setting a keyguard password for keystore in a multi-user setup
while we're at it.
Bug: 16233206.
Change-Id: I7941707ca66ac25bd122fd22e5e0f639e7af697e
| -rw-r--r-- | core/java/android/security/IKeystoreService.java | 62 | ||||
| -rw-r--r-- | keystore/java/android/security/KeyStore.java | 30 | ||||
| -rw-r--r-- | services/core/java/com/android/server/LockSettingsService.java | 73 |
3 files changed, 155 insertions, 10 deletions
diff --git a/core/java/android/security/IKeystoreService.java b/core/java/android/security/IKeystoreService.java index f8bf45b..7e9aba0 100644 --- a/core/java/android/security/IKeystoreService.java +++ b/core/java/android/security/IKeystoreService.java @@ -478,6 +478,59 @@ public interface IKeystoreService extends IInterface { } return _result; } + + public int reset_uid(int uid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(uid); + mRemote.transact(Stub.TRANSACTION_reset_uid, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int sync_uid(int srcUid, int dstUid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeInt(srcUid); + _data.writeInt(dstUid); + mRemote.transact(Stub.TRANSACTION_sync_uid, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } + + public int password_uid(String password, int uid) throws RemoteException { + Parcel _data = Parcel.obtain(); + Parcel _reply = Parcel.obtain(); + int _result; + try { + _data.writeInterfaceToken(DESCRIPTOR); + _data.writeString(password); + _data.writeInt(uid); + mRemote.transact(Stub.TRANSACTION_password_uid, _data, _reply, 0); + _reply.readException(); + _result = _reply.readInt(); + } finally { + _reply.recycle(); + _data.recycle(); + } + return _result; + } } private static final String DESCRIPTOR = "android.security.keystore"; @@ -505,6 +558,9 @@ public interface IKeystoreService extends IInterface { static final int TRANSACTION_duplicate = IBinder.FIRST_CALL_TRANSACTION + 20; static final int TRANSACTION_is_hardware_backed = IBinder.FIRST_CALL_TRANSACTION + 21; static final int TRANSACTION_clear_uid = IBinder.FIRST_CALL_TRANSACTION + 22; + static final int TRANSACTION_reset_uid = IBinder.FIRST_CALL_TRANSACTION + 23; + static final int TRANSACTION_sync_uid = IBinder.FIRST_CALL_TRANSACTION + 24; + static final int TRANSACTION_password_uid = IBinder.FIRST_CALL_TRANSACTION + 25; /** * Cast an IBinder object into an IKeystoreService interface, generating @@ -597,4 +653,10 @@ public interface IKeystoreService extends IInterface { public int is_hardware_backed(String string) throws RemoteException; public int clear_uid(long uid) throws RemoteException; + + public int reset_uid(int uid) throws RemoteException; + + public int sync_uid(int sourceUid, int targetUid) throws RemoteException; + + public int password_uid(String password, int uid) throws RemoteException; } diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 6ac49ee..0db8c77 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -331,6 +331,36 @@ public class KeyStore { } } + public boolean resetUid(int uid) { + try { + mError = mBinder.reset_uid(uid); + return mError == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } + } + + public boolean syncUid(int sourceUid, int targetUid) { + try { + mError = mBinder.sync_uid(sourceUid, targetUid); + return mError == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } + } + + public boolean passwordUid(String password, int uid) { + try { + mError = mBinder.password_uid(password, uid); + return mError == NO_ERROR; + } catch (RemoteException e) { + Log.w(TAG, "Cannot connect to keystore", e); + return false; + } + } + public int getLastError() { return mError; } diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 86ce961..92f5170 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -16,9 +16,12 @@ package com.android.server; +import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.UserInfo; @@ -31,6 +34,7 @@ import android.database.sqlite.SQLiteStatement; import android.os.Binder; import android.os.Environment; import android.os.IBinder; +import android.os.Process; import android.os.RemoteException; import android.os.storage.IMountService; import android.os.ServiceManager; @@ -41,11 +45,14 @@ import android.os.UserManager; import android.provider.Settings; import android.provider.Settings.Secure; import android.provider.Settings.SettingNotFoundException; +import android.security.KeyChain; +import android.security.KeyChain.KeyChainConnection; import android.security.KeyStore; import android.text.TextUtils; import android.util.Log; import android.util.Slog; +import com.android.internal.os.BackgroundThread; import com.android.internal.widget.ILockSettings; import com.android.internal.widget.ILockSettingsObserver; import com.android.internal.widget.LockPatternUtils; @@ -99,8 +106,30 @@ public class LockSettingsService extends ILockSettings.Stub { mLockPatternUtils = new LockPatternUtils(context); mFirstCallToVold = true; + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_USER_ADDED); + mContext.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null); } + private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // Update keystore settings for profiles which use the same password as their parent + if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) { + final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0); + final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); + final UserInfo parentInfo = um.getProfileParent(userHandle); + if (parentInfo != null) { + final KeyStore ks = KeyStore.getInstance(); + final int profileUid = UserHandle.getUid(userHandle, Process.SYSTEM_UID); + final int parentUid = UserHandle.getUid(parentInfo.id, Process.SYSTEM_UID); + ks.syncUid(parentUid, profileUid); + } + } + } + }; + public void systemReady() { migrateOldData(); } @@ -275,6 +304,17 @@ public class LockSettingsService extends ILockSettings.Stub { } } + private int getUserParentOrSelfId(int userId) { + if (userId != 0) { + final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); + final UserInfo pi = um.getProfileParent(userId); + if (pi != null) { + return pi.id; + } + } + return userId; + } + private String getLockPatternFilename(int userId) { String dataSystemDirectory = android.os.Environment.getDataDirectory().getAbsolutePath() + @@ -283,6 +323,7 @@ public class LockSettingsService extends ILockSettings.Stub { // Leave it in the same place for user 0 return dataSystemDirectory + LOCK_PATTERN_FILE; } else { + userId = getUserParentOrSelfId(userId); return new File(Environment.getUserSystemDirectory(userId), LOCK_PATTERN_FILE) .getAbsolutePath(); } @@ -296,7 +337,8 @@ public class LockSettingsService extends ILockSettings.Stub { // Leave it in the same place for user 0 return dataSystemDirectory + LOCK_PASSWORD_FILE; } else { - return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE) + userId = getUserParentOrSelfId(userId); + return new File(Environment.getUserSystemDirectory(userId), LOCK_PASSWORD_FILE) .getAbsolutePath(); } } @@ -315,16 +357,27 @@ public class LockSettingsService extends ILockSettings.Stub { return new File(getLockPatternFilename(userId)).length() > 0; } - private void maybeUpdateKeystore(String password, int userId) { - if (userId == UserHandle.USER_OWNER) { - final KeyStore keyStore = KeyStore.getInstance(); - // Conditionally reset the keystore if empty. If non-empty, we are just - // switching key guard type - if (TextUtils.isEmpty(password) && keyStore.isEmpty()) { - keyStore.reset(); + private void maybeUpdateKeystore(String password, int userHandle) { + final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); + final KeyStore ks = KeyStore.getInstance(); + + final List<UserInfo> profiles = um.getProfiles(userHandle); + boolean shouldReset = TextUtils.isEmpty(password); + + // For historical reasons, don't wipe a non-empty keystore if we have a single user with a + // single profile. + if (userHandle == UserHandle.USER_OWNER && profiles.size() == 1) { + if (!ks.isEmpty()) { + shouldReset = false; + } + } + + for (UserInfo pi : profiles) { + final int profileUid = UserHandle.getUid(pi.id, Process.SYSTEM_UID); + if (shouldReset) { + ks.resetUid(profileUid); } else { - // Update the keystore password - keyStore.password(password); + ks.passwordUid(password, profileUid); } } } |
