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

Commit b8e68385 authored by Paul Lawrence's avatar Paul Lawrence Committed by Android (Google) Code Review
Browse files

Merge "Fix adb backup for encrypted case" into lmp-dev

parents 306908f2 32d06732
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@
    <string name="backup_enc_password_text">Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:</string>
    <!-- Text for message to user that they may optionally supply an encryption password to use for a full backup operation. -->
    <string name="backup_enc_password_optional">If you wish to encrypt the full backup data, enter a password below:</string>
    <!-- Text for message to user that they must supply an encryption password to use for a full backup operation because their phone is locked. -->
    <string name="backup_enc_password_required">Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:</string>

    <!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
    <string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
+10 −18
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.util.Log;
import android.util.Slog;
import android.view.View;
@@ -182,25 +183,14 @@ public class BackupRestoreConfirmation extends Activity {
        // We vary the password prompt depending on whether one is predefined, and whether
        // the device is encrypted.
        mIsEncrypted = deviceIsEncrypted();
        if (mIsEncrypted) {
            Log.d(TAG, "Device is encrypted: requiring encryption pw");
            TextView pwPrompt = (TextView) findViewById(R.id.password_desc);
            // this password is mandatory; we hide the other options during backup
            if (layoutId == R.layout.confirm_backup) {
                pwPrompt.setText(R.string.device_encryption_backup_text);
                TextView tv = (TextView) findViewById(R.id.enc_password);
                tv.setVisibility(View.GONE);
                tv = (TextView) findViewById(R.id.enc_password_desc);
                tv.setVisibility(View.GONE);
            } else {
                pwPrompt.setText(R.string.device_encryption_restore_text);
            }
        } else if (!haveBackupPassword()) {
        if (!haveBackupPassword()) {
            curPwDesc.setVisibility(View.GONE);
            mCurPassword.setVisibility(View.GONE);
            if (layoutId == R.layout.confirm_backup) {
                TextView encPwDesc = (TextView) findViewById(R.id.enc_password_desc);
                encPwDesc.setText(R.string.backup_enc_password_optional);
                encPwDesc.setText(mIsEncrypted
                                  ? R.string.backup_enc_password_required
                                  : R.string.backup_enc_password_optional);
            }
        }

@@ -246,8 +236,7 @@ public class BackupRestoreConfirmation extends Activity {
            mDidAcknowledge = true;

            try {
                CharSequence encPassword = (mIsEncrypted)
                        ? mCurPassword.getText() : mEncPassword.getText();
                CharSequence encPassword = mEncPassword.getText();
                mBackupManager.acknowledgeFullBackupOrRestore(mToken,
                        allow,
                        String.valueOf(mCurPassword.getText()),
@@ -261,7 +250,10 @@ public class BackupRestoreConfirmation extends Activity {

    boolean deviceIsEncrypted() {
        try {
            return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE);
            return mMountService.getEncryptionState()
                     != IMountService.ENCRYPTION_STATE_NONE
                && mMountService.getPasswordType()
                     != StorageManager.CRYPT_TYPE_DEFAULT;
        } catch (Exception e) {
            // If we can't talk to the mount service we have a serious problem; fail
            // "secure" i.e. assuming that the device is encrypted.
+25 −56
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ import android.os.UserHandle;
import android.os.WorkSource;
import android.os.Environment.UserEnvironment;
import android.os.storage.IMountService;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.system.ErrnoException;
import android.system.Os;
@@ -1430,43 +1431,7 @@ public class BackupManagerService extends IBackupManager.Stub {
        return array;
    }

    // Backup password management
    boolean passwordMatchesSaved(String algorithm, String candidatePw, int rounds) {
        // First, on an encrypted device we require matching the device pw
        final boolean isEncrypted;
        try {
            isEncrypted = (mMountService.getEncryptionState() !=
                    IMountService.ENCRYPTION_STATE_NONE);
            if (isEncrypted) {
                if (DEBUG) {
                    Slog.i(TAG, "Device encrypted; verifying against device data pw");
                }
                // 0 means the password validated
                // -2 means device not encrypted
                // Any other result is either password failure or an error condition,
                // so we refuse the match
                final int result = mMountService.verifyEncryptionPassword(candidatePw);
                if (result == 0) {
                    if (MORE_DEBUG) Slog.d(TAG, "Pw verifies");
                    return true;
                } else if (result != -2) {
                    if (MORE_DEBUG) Slog.d(TAG, "Pw mismatch");
                    return false;
                } else {
                    // ...else the device is supposedly not encrypted.  HOWEVER, the
                    // query about the encryption state said that the device *is*
                    // encrypted, so ... we may have a problem.  Log it and refuse
                    // the backup.
                    Slog.e(TAG, "verified encryption state mismatch against query; no match allowed");
                    return false;
                }
            }
        } catch (Exception e) {
            // Something went wrong talking to the mount service.  This is very bad;
            // assume that we fail password validation.
            return false;
        }

        if (mPasswordHash == null) {
            // no current password case -- require that 'currentPw' be null or empty
            if (candidatePw == null || "".equals(candidatePw)) {
@@ -1571,14 +1536,7 @@ public class BackupManagerService extends IBackupManager.Stub {
        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP,
                "hasBackupPassword");

        try {
            return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE)
                || (mPasswordHash != null && mPasswordHash.length() > 0);
        } catch (Exception e) {
            // If we can't talk to the mount service we have a serious problem; fail
            // "secure" i.e. assuming that we require a password
            return true;
        }
        return mPasswordHash != null && mPasswordHash.length() > 0;
    }

    private boolean backupPasswordMatches(String currentPw) {
@@ -3341,6 +3299,20 @@ public class BackupManagerService extends IBackupManager.Stub {
        }
    }

    boolean deviceIsEncrypted() {
        try {
            return mMountService.getEncryptionState()
                     != IMountService.ENCRYPTION_STATE_NONE
                && mMountService.getPasswordType()
                     != StorageManager.CRYPT_TYPE_DEFAULT;
        } catch (Exception e) {
            // If we can't talk to the mount service we have a serious problem; fail
            // "secure" i.e. assuming that the device is encrypted.
            Slog.e(TAG, "Unable to communicate with mount service: " + e.getMessage());
            return true;
        }
    }

    // Full backup task variant used for adb backup
    class PerformAdbBackupTask extends FullBackupTask {
        FullBackupEngine mBackupEngine;
@@ -3555,6 +3527,13 @@ public class BackupManagerService extends IBackupManager.Stub {
            PackageInfo pkg = null;
            try {
                boolean encrypting = (mEncryptPassword != null && mEncryptPassword.length() > 0);

                // Only allow encrypted backups of encrypted devices
                if (deviceIsEncrypted() && !encrypting) {
                    Slog.e(TAG, "Unencrypted backup of encrypted device; aborting");
                    return;
                }

                OutputStream finalOutput = ofstream;

                // Verify that the given password matches the currently-active
@@ -8335,17 +8314,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
                        params.observer = observer;
                        params.curPassword = curPassword;

                        boolean isEncrypted;
                        try {
                            isEncrypted = (mMountService.getEncryptionState() !=
                                    IMountService.ENCRYPTION_STATE_NONE);
                            if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password");
                        } catch (RemoteException e) {
                            // couldn't contact the mount service; fail "safe" and assume encryption
                            Slog.e(TAG, "Unable to contact mount service!");
                            isEncrypted = true;
                        }
                        params.encryptPassword = (isEncrypted) ? curPassword : encPpassword;
                        params.encryptPassword = encPpassword;

                        if (DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb);
                        mWakelock.acquire();