Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bccf6f03 authored by Robin Lee's avatar Robin Lee Committed by Android (Google) Code Review
Browse files

Merge "Keep managed profile keystores in sync with owner" into lmp-dev

parents 95c047d9 f0246a8a
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
@@ -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;
}
+30 −0
Original line number Diff line number Diff line
@@ -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;
    }
+63 −10
Original line number Diff line number Diff line
@@ -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,7 +106,29 @@ 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,6 +337,7 @@ public class LockSettingsService extends ILockSettings.Stub {
            // Leave it in the same place for user 0
            return dataSystemDirectory + LOCK_PASSWORD_FILE;
        } else {
            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);
            }
        }
    }