|
62 | 62 | import android.os.PowerManager; |
63 | 63 | import android.os.Process; |
64 | 64 | import android.os.RemoteException; |
| 65 | +import android.os.ServiceManager; |
65 | 66 | import android.os.SystemClock; |
66 | 67 | import android.os.WorkSource; |
| 68 | +import android.os.storage.IMountService; |
67 | 69 | import android.provider.Settings; |
68 | 70 | import android.util.EventLog; |
69 | 71 | import android.util.Log; |
70 | 72 | import android.util.Slog; |
71 | 73 | import android.util.SparseArray; |
72 | | -import android.util.SparseIntArray; |
73 | 74 | import android.util.StringBuilderPrinter; |
74 | 75 |
|
75 | 76 | import com.android.internal.backup.BackupConstants; |
@@ -187,6 +188,7 @@ class BackupManagerService extends IBackupManager.Stub { |
187 | 188 | private IActivityManager mActivityManager; |
188 | 189 | private PowerManager mPowerManager; |
189 | 190 | private AlarmManager mAlarmManager; |
| 191 | + private IMountService mMountService; |
190 | 192 | IBackupManager mBackupManagerBinder; |
191 | 193 |
|
192 | 194 | boolean mEnabled; // access to this is synchronized on 'this' |
@@ -660,6 +662,7 @@ public BackupManagerService(Context context) { |
660 | 662 |
|
661 | 663 | mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); |
662 | 664 | mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); |
| 665 | + mMountService = IMountService.Stub.asInterface(ServiceManager.getService("mount")); |
663 | 666 |
|
664 | 667 | mBackupManagerBinder = asInterface(asBinder()); |
665 | 668 |
|
@@ -1037,6 +1040,40 @@ private byte[] randomBytes(int bits) { |
1037 | 1040 |
|
1038 | 1041 | // Backup password management |
1039 | 1042 | boolean passwordMatchesSaved(String candidatePw, int rounds) { |
| 1043 | + // First, on an encrypted device we require matching the device pw |
| 1044 | + final boolean isEncrypted; |
| 1045 | + try { |
| 1046 | + isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE); |
| 1047 | + if (isEncrypted) { |
| 1048 | + if (DEBUG) { |
| 1049 | + Slog.i(TAG, "Device encrypted; verifying against device data pw"); |
| 1050 | + } |
| 1051 | + // 0 means the password validated |
| 1052 | + // -2 means device not encrypted |
| 1053 | + // Any other result is either password failure or an error condition, |
| 1054 | + // so we refuse the match |
| 1055 | + final int result = mMountService.verifyEncryptionPassword(candidatePw); |
| 1056 | + if (result == 0) { |
| 1057 | + if (MORE_DEBUG) Slog.d(TAG, "Pw verifies"); |
| 1058 | + return true; |
| 1059 | + } else if (result != -2) { |
| 1060 | + if (MORE_DEBUG) Slog.d(TAG, "Pw mismatch"); |
| 1061 | + return false; |
| 1062 | + } else { |
| 1063 | + // ...else the device is supposedly not encrypted. HOWEVER, the |
| 1064 | + // query about the encryption state said that the device *is* |
| 1065 | + // encrypted, so ... we may have a problem. Log it and refuse |
| 1066 | + // the backup. |
| 1067 | + Slog.e(TAG, "verified encryption state mismatch against query; no match allowed"); |
| 1068 | + return false; |
| 1069 | + } |
| 1070 | + } |
| 1071 | + } catch (Exception e) { |
| 1072 | + // Something went wrong talking to the mount service. This is very bad; |
| 1073 | + // assume that we fail password validation. |
| 1074 | + return false; |
| 1075 | + } |
| 1076 | + |
1040 | 1077 | if (mPasswordHash == null) { |
1041 | 1078 | // no current password case -- require that 'currentPw' be null or empty |
1042 | 1079 | if (candidatePw == null || "".equals(candidatePw)) { |
@@ -1114,7 +1151,15 @@ public boolean setBackupPassword(String currentPw, String newPw) { |
1114 | 1151 | public boolean hasBackupPassword() { |
1115 | 1152 | mContext.enforceCallingOrSelfPermission(android.Manifest.permission.BACKUP, |
1116 | 1153 | "hasBackupPassword"); |
1117 | | - return (mPasswordHash != null && mPasswordHash.length() > 0); |
| 1154 | + |
| 1155 | + try { |
| 1156 | + return (mMountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE) |
| 1157 | + || (mPasswordHash != null && mPasswordHash.length() > 0); |
| 1158 | + } catch (Exception e) { |
| 1159 | + // If we can't talk to the mount service we have a serious problem; fail |
| 1160 | + // "secure" i.e. assuming that we require a password |
| 1161 | + return true; |
| 1162 | + } |
1118 | 1163 | } |
1119 | 1164 |
|
1120 | 1165 | // Maintain persistent state around whether need to do an initialize operation. |
@@ -5007,7 +5052,17 @@ public void acknowledgeFullBackupOrRestore(int token, boolean allow, |
5007 | 5052 |
|
5008 | 5053 | params.observer = observer; |
5009 | 5054 | params.curPassword = curPassword; |
5010 | | - params.encryptPassword = encPpassword; |
| 5055 | + |
| 5056 | + boolean isEncrypted; |
| 5057 | + try { |
| 5058 | + isEncrypted = (mMountService.getEncryptionState() != MountService.ENCRYPTION_STATE_NONE); |
| 5059 | + if (isEncrypted) Slog.w(TAG, "Device is encrypted; forcing enc password"); |
| 5060 | + } catch (RemoteException e) { |
| 5061 | + // couldn't contact the mount service; fail "safe" and assume encryption |
| 5062 | + Slog.e(TAG, "Unable to contact mount service!"); |
| 5063 | + isEncrypted = true; |
| 5064 | + } |
| 5065 | + params.encryptPassword = (isEncrypted) ? curPassword : encPpassword; |
5011 | 5066 |
|
5012 | 5067 | if (DEBUG) Slog.d(TAG, "Sending conf message with verb " + verb); |
5013 | 5068 | mWakelock.acquire(); |
|
0 commit comments