mirror of
https://github.com/bitwarden/mobile
synced 2026-01-04 09:33:16 +00:00
[PM-3726] prevent legacy user login (#2769)
* [PM-3726] prevent legacy user login * [PM-3726] prevent unlock or auto key migration if legacy user * [PM-3726] add legacy checks to lock page and refactor * [PM-3726] rethrow exception from pin * formatting * [PM-3726] add changes to LockViewController, consolidate logout calls * formatting * [PM-3726] pr feedback * generate resx * formatting
This commit is contained in:
@@ -477,6 +477,17 @@ namespace Bit.Core.Services
|
||||
}
|
||||
|
||||
var tokenResponse = response.TokenResponse;
|
||||
if (localHashedPassword != null && tokenResponse.Key == null)
|
||||
{
|
||||
// Only check for legacy if there is no key on token
|
||||
if (await _cryptoService.IsLegacyUserAsync(masterKey))
|
||||
{
|
||||
// Legacy users must migrate on web vault;
|
||||
result.RequiresEncryptionKeyMigration = true;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.ResetMasterPassword = tokenResponse.ResetMasterPassword;
|
||||
result.ForcePasswordReset = tokenResponse.ForcePasswordReset;
|
||||
_masterPasswordPolicy = tokenResponse.MasterPasswordPolicy;
|
||||
|
||||
@@ -62,6 +62,16 @@ namespace Bit.Core.Services
|
||||
return _stateService.GetUserKeyAsync(userId);
|
||||
}
|
||||
|
||||
public async Task<bool> IsLegacyUserAsync(MasterKey masterKey = null, string userId = null)
|
||||
{
|
||||
masterKey ??= await GetMasterKeyAsync(userId);
|
||||
if (masterKey == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return await ValidateUserKeyAsync(new UserKey(masterKey.Key));
|
||||
}
|
||||
|
||||
public async Task<UserKey> GetUserKeyWithLegacySupportAsync(string userId = null)
|
||||
{
|
||||
var userKey = await GetUserKeyAsync(userId);
|
||||
@@ -997,6 +1007,31 @@ namespace Bit.Core.Services
|
||||
return keyCreator(key);
|
||||
}
|
||||
|
||||
private async Task<bool> ValidateUserKeyAsync(UserKey key, string userId = null)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var encPrivateKey = await _stateService.GetPrivateKeyEncryptedAsync(userId);
|
||||
if (encPrivateKey == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var privateKey = await DecryptToBytesAsync(new EncString(encPrivateKey), key);
|
||||
await _cryptoFunctionService.RsaExtractPublicKeyAsync(privateKey);
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class EncryptedObject
|
||||
{
|
||||
public byte[] Iv { get; set; }
|
||||
@@ -1019,6 +1054,10 @@ namespace Bit.Core.Services
|
||||
|
||||
// Decrypt
|
||||
var masterKey = new MasterKey(Convert.FromBase64String(oldKey));
|
||||
if (await IsLegacyUserAsync(masterKey, userId))
|
||||
{
|
||||
throw new LegacyUserException();
|
||||
}
|
||||
var encryptedUserKey = await _stateService.GetEncKeyEncryptedAsync(userId);
|
||||
if (encryptedUserKey == null)
|
||||
{
|
||||
@@ -1058,6 +1097,10 @@ namespace Bit.Core.Services
|
||||
kdfConfig,
|
||||
oldPinKey
|
||||
);
|
||||
if (await IsLegacyUserAsync(masterKey))
|
||||
{
|
||||
throw new LegacyUserException();
|
||||
}
|
||||
var encUserKey = await _stateService.GetEncKeyEncryptedAsync();
|
||||
var userKey = await DecryptUserKeyWithMasterKeyAsync(
|
||||
masterKey,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
using System.Threading.Tasks;
|
||||
using Bit.Core.Abstractions;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Domain;
|
||||
|
||||
namespace Bit.Core.Services
|
||||
{
|
||||
@@ -67,14 +69,23 @@ namespace Bit.Core.Services
|
||||
|
||||
if (!await _cryptoService.HasUserKeyAsync(userId))
|
||||
{
|
||||
if (!await _cryptoService.HasAutoUnlockKeyAsync(userId))
|
||||
try
|
||||
{
|
||||
return true;
|
||||
if (!await _cryptoService.HasAutoUnlockKeyAsync(userId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (userId != null && await _stateService.GetActiveUserIdAsync() != userId)
|
||||
{
|
||||
await _cryptoService.SetUserKeyAsync(await _cryptoService.GetAutoUnlockKeyAsync(userId),
|
||||
userId);
|
||||
}
|
||||
}
|
||||
if (userId != null && await _stateService.GetActiveUserIdAsync() != userId)
|
||||
catch (LegacyUserException)
|
||||
{
|
||||
await _cryptoService.SetUserKeyAsync(await _cryptoService.GetAutoUnlockKeyAsync(userId), userId);
|
||||
await LogOutAsync(false, userId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Check again to verify auto key was set
|
||||
|
||||
Reference in New Issue
Block a user