mirror of
https://github.com/bitwarden/server.git
synced 2026-01-16 23:01:09 +00:00
Some checks failed
Collect code references / Check for secret access (push) Waiting to run
Collect code references / Code reference collection (push) Blocked by required conditions
Scan / Sonar (push) Blocked by required conditions
Scan / Check PR run (push) Waiting to run
Scan / Checkmarx (push) Blocked by required conditions
Testing / Run tests (push) Waiting to run
Database testing / Run tests (push) Has been cancelled
Database testing / Run validation (push) Has been cancelled
Database testing / Validate new migration naming and order (push) Has been cancelled
* V2 prep, rename existing SSO JIT MP command to V1 * set initial master password for account registraton V2 * later removel docs * TDE MP onboarding split * revert separate TDE onboarding controller api * Server side hash of the user master password hash * use `ValidationResult` instead for validation errors * unit test coverage * integration test coverage * update sql migration script date * revert validate password change * better requests validation * explicit error message when org sso identifier invalid * more unit test coverage * renamed onboarding to set, hash naming clarifications * update db sql script, formatting * use raw json as request instead of request models for integration test * v1 integration test coverage * change of name
160 lines
5.5 KiB
C#
160 lines
5.5 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using Bit.Api.KeyManagement.Models.Requests;
|
|
using Bit.Core.Auth.Models.Api.Request.Accounts;
|
|
using Bit.Core.Auth.Models.Data;
|
|
using Bit.Core.Entities;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.KeyManagement.Models.Api.Request;
|
|
using Bit.Core.Utilities;
|
|
|
|
namespace Bit.Api.Auth.Models.Request.Accounts;
|
|
|
|
public class SetInitialPasswordRequestModel : IValidatableObject
|
|
{
|
|
// TODO will be removed with https://bitwarden.atlassian.net/browse/PM-27327
|
|
[Obsolete("Use MasterPasswordAuthentication instead")]
|
|
[StringLength(300)]
|
|
public string? MasterPasswordHash { get; set; }
|
|
|
|
[Obsolete("Use MasterPasswordUnlock instead")]
|
|
public string? Key { get; set; }
|
|
|
|
[Obsolete("Use AccountKeys instead")]
|
|
public KeysRequestModel? Keys { get; set; }
|
|
|
|
[Obsolete("Use MasterPasswordAuthentication instead")]
|
|
public KdfType? Kdf { get; set; }
|
|
|
|
[Obsolete("Use MasterPasswordAuthentication instead")]
|
|
public int? KdfIterations { get; set; }
|
|
|
|
[Obsolete("Use MasterPasswordAuthentication instead")]
|
|
public int? KdfMemory { get; set; }
|
|
|
|
[Obsolete("Use MasterPasswordAuthentication instead")]
|
|
public int? KdfParallelism { get; set; }
|
|
|
|
public MasterPasswordAuthenticationDataRequestModel? MasterPasswordAuthentication { get; set; }
|
|
public MasterPasswordUnlockDataRequestModel? MasterPasswordUnlock { get; set; }
|
|
public AccountKeysRequestModel? AccountKeys { get; set; }
|
|
|
|
[StringLength(50)]
|
|
public string? MasterPasswordHint { get; set; }
|
|
|
|
[Required]
|
|
public required string OrgIdentifier { get; set; }
|
|
|
|
// TODO removed with https://bitwarden.atlassian.net/browse/PM-27327
|
|
public User ToUser(User existingUser)
|
|
{
|
|
existingUser.MasterPasswordHint = MasterPasswordHint;
|
|
existingUser.Kdf = Kdf!.Value;
|
|
existingUser.KdfIterations = KdfIterations!.Value;
|
|
existingUser.KdfMemory = KdfMemory;
|
|
existingUser.KdfParallelism = KdfParallelism;
|
|
existingUser.Key = Key;
|
|
Keys?.ToUser(existingUser);
|
|
return existingUser;
|
|
}
|
|
|
|
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
|
|
{
|
|
if (IsV2Request())
|
|
{
|
|
// V2 registration
|
|
|
|
// Validate Kdf
|
|
var authenticationKdf = MasterPasswordAuthentication!.Kdf.ToData();
|
|
var unlockKdf = MasterPasswordUnlock!.Kdf.ToData();
|
|
|
|
// Currently, KDF settings are not saved separately for authentication and unlock and must therefore be equal
|
|
if (!authenticationKdf.Equals(unlockKdf))
|
|
{
|
|
yield return new ValidationResult("KDF settings must be equal for authentication and unlock.",
|
|
[$"{nameof(MasterPasswordAuthentication)}.{nameof(MasterPasswordAuthenticationDataRequestModel.Kdf)}",
|
|
$"{nameof(MasterPasswordUnlock)}.{nameof(MasterPasswordUnlockDataRequestModel.Kdf)}"]);
|
|
}
|
|
|
|
var authenticationValidationErrors = KdfSettingsValidator.Validate(authenticationKdf).ToList();
|
|
if (authenticationValidationErrors.Count != 0)
|
|
{
|
|
yield return authenticationValidationErrors.First();
|
|
}
|
|
|
|
var unlockValidationErrors = KdfSettingsValidator.Validate(unlockKdf).ToList();
|
|
if (unlockValidationErrors.Count != 0)
|
|
{
|
|
yield return unlockValidationErrors.First();
|
|
}
|
|
|
|
yield break;
|
|
}
|
|
|
|
// V1 registration
|
|
// TODO removed with https://bitwarden.atlassian.net/browse/PM-27327
|
|
if (string.IsNullOrEmpty(MasterPasswordHash))
|
|
{
|
|
yield return new ValidationResult("MasterPasswordHash must be supplied.");
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(Key))
|
|
{
|
|
yield return new ValidationResult("Key must be supplied.");
|
|
}
|
|
|
|
if (Kdf == null)
|
|
{
|
|
yield return new ValidationResult("Kdf must be supplied.");
|
|
yield break;
|
|
}
|
|
|
|
if (KdfIterations == null)
|
|
{
|
|
yield return new ValidationResult("KdfIterations must be supplied.");
|
|
yield break;
|
|
}
|
|
|
|
if (Kdf == KdfType.Argon2id)
|
|
{
|
|
if (KdfMemory == null)
|
|
{
|
|
yield return new ValidationResult("KdfMemory must be supplied when Kdf is Argon2id.");
|
|
}
|
|
|
|
if (KdfParallelism == null)
|
|
{
|
|
yield return new ValidationResult("KdfParallelism must be supplied when Kdf is Argon2id.");
|
|
}
|
|
}
|
|
|
|
var validationErrors = KdfSettingsValidator
|
|
.Validate(Kdf!.Value, KdfIterations!.Value, KdfMemory, KdfParallelism).ToList();
|
|
if (validationErrors.Count != 0)
|
|
{
|
|
yield return validationErrors.First();
|
|
}
|
|
}
|
|
|
|
public bool IsV2Request()
|
|
{
|
|
// AccountKeys can be null for TDE users, so we don't check that here
|
|
return MasterPasswordAuthentication != null && MasterPasswordUnlock != null;
|
|
}
|
|
|
|
public bool IsTdeSetPasswordRequest()
|
|
{
|
|
return AccountKeys == null;
|
|
}
|
|
|
|
public SetInitialMasterPasswordDataModel ToData()
|
|
{
|
|
return new SetInitialMasterPasswordDataModel
|
|
{
|
|
MasterPasswordAuthentication = MasterPasswordAuthentication!.ToData(),
|
|
MasterPasswordUnlock = MasterPasswordUnlock!.ToData(),
|
|
OrgSsoIdentifier = OrgIdentifier,
|
|
AccountKeys = AccountKeys?.ToAccountKeysData(),
|
|
MasterPasswordHint = MasterPasswordHint
|
|
};
|
|
}
|
|
}
|