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

Commit 790b9de7 authored by Eric Biggers's avatar Eric Biggers
Browse files

Stop allowing nonempty tokens/secrets in "am unlock-user"

It doesn't make sense for the 'am unlock-user' shell command to accept a
token and secret, given that the token is no longer used, and there
isn't really any way for the caller to get the secret if a nonempty
secret is needed.  Therefore, make it so that these two parameters must
be either empty or not specified.  This makes this command more
explicitly only support unlocking users who don't have an LSKF.

Test: atest com.android.server.locksettings
Test: am unlock-user 10
Test: am unlock-user 10 "" ""
Bug: 184723544
Change-Id: Ie4bfac19ba6b753b3434e13be553a654e5a2df35
parent 747a0b78
Loading
Loading
Loading
Loading
+34 −14
Original line number Diff line number Diff line
@@ -101,7 +101,6 @@ import android.view.Display;
import android.window.SplashScreen;

import com.android.internal.compat.CompatibilityChangeConfig;
import com.android.internal.util.HexDump;
import com.android.internal.util.MemInfoReader;
import com.android.server.am.LowMemDetector.MemFactor;
import com.android.server.compat.PlatformCompat;
@@ -1958,22 +1957,42 @@ final class ActivityManagerShellCommand extends ShellCommand {
        return 0;
    }

    private static byte[] argToBytes(String arg) {
        if (arg.equals("!")) {
            return null;
        } else {
            return HexDump.hexStringToByteArray(arg);
    int runUnlockUser(PrintWriter pw) throws RemoteException {
        int userId = Integer.parseInt(getNextArgRequired());

        /*
         * Originally this command required two more parameters: the hardware
         * authentication token and secret needed to unlock the user.  However,
         * unlockUser() no longer takes a token parameter at all, and there
         * isn't really any way for callers of this shell command to get the
         * secret if one is needed (i.e., when the user has an LSKF), given that
         * the secret must be a cryptographic key derived from the user's
         * synthetic password.  I.e. the secret is *not* the LSKF here, but
         * rather an intermediate value several steps down the chain.
         *
         * As such, the only supported use for this command is unlocking a user
         * who doesn't have an LSKF, with empty or unspecified token and secret.
         *
         * To preserve previous behavior, an exclamation mark ("!") is also
         * accepted for these values; it means the same as an empty string.
         */
        String token = getNextArg();
        if (!TextUtils.isEmpty(token) && !"!".equals(token)) {
            getErrPrintWriter().println("Error: token parameter not supported");
            return -1;
        }
        String secret = getNextArg();
        if (!TextUtils.isEmpty(secret) && !"!".equals(secret)) {
            getErrPrintWriter().println("Error: secret parameter not supported");
            return -1;
        }

    int runUnlockUser(PrintWriter pw) throws RemoteException {
        int userId = Integer.parseInt(getNextArgRequired());
        byte[] token = argToBytes(getNextArgRequired());
        byte[] secret = argToBytes(getNextArgRequired());
        boolean success = mInterface.unlockUser(userId, token, secret, null);
        boolean success = mInterface.unlockUser(userId, null, null, null);
        if (success) {
            pw.println("Success: user unlocked");
        } else {
            // TODO(b/218389026): we can reach here even if the user's storage
            // was successfully unlocked.
            getErrPrintWriter().println("Error: could not unlock user");
        }
        return 0;
@@ -3494,8 +3513,9 @@ final class ActivityManagerShellCommand extends ShellCommand {
            pw.println("      Start USER_ID in background if it is currently stopped;");
            pw.println("      use switch-user if you want to start the user in foreground.");
            pw.println("      -w: wait for start-user to complete and the user to be unlocked.");
            pw.println("  unlock-user <USER_ID> [TOKEN_HEX]");
            pw.println("      Attempt to unlock the given user using the given authorization token.");
            pw.println("  unlock-user <USER_ID>");
            pw.println("      Unlock the given user.  This will only work if the user doesn't");
            pw.println("      have an LSKF (PIN/pattern/password).");
            pw.println("  stop-user [-w] [-f] <USER_ID>");
            pw.println("      Stop execution of USER_ID, not allowing it to run any");
            pw.println("      code until a later explicit start or switch to it.");