Enforce Passphrase Policy (#772)

* Enforce passphrase policy

* Update multi-line conditional formatting

* Updated formatting round 2

Co-authored-by: Vincent Salucci <vsalucci@bitwarden.com>
This commit is contained in:
Vincent Salucci 2020-03-13 23:02:38 -05:00 committed by GitHub
parent a4eff45534
commit df8f44d77d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 87 additions and 4 deletions

View File

@ -132,6 +132,8 @@
HorizontalOptions="StartAndExpand" /> HorizontalOptions="StartAndExpand" />
<Switch <Switch
IsToggled="{Binding Capitalize}" IsToggled="{Binding Capitalize}"
IsEnabled="{Binding EnforcedPolicyOptions.Capitalize,
Converter={StaticResource inverseBool}}"
StyleClass="box-value" StyleClass="box-value"
HorizontalOptions="End" /> HorizontalOptions="End" />
</StackLayout> </StackLayout>
@ -143,6 +145,8 @@
HorizontalOptions="StartAndExpand" /> HorizontalOptions="StartAndExpand" />
<Switch <Switch
IsToggled="{Binding IncludeNumber}" IsToggled="{Binding IncludeNumber}"
IsEnabled="{Binding EnforcedPolicyOptions.IncludeNumber,
Converter={StaticResource inverseBool}}"
StyleClass="box-value" StyleClass="box-value"
HorizontalOptions="End" /> HorizontalOptions="End" />
</StackLayout> </StackLayout>

View File

@ -233,10 +233,7 @@ namespace Bit.App.Pages
}); });
} }
public bool IsPolicyInEffect => _enforcedPolicyOptions.MinLength > 0 || _enforcedPolicyOptions.UseUppercase || public bool IsPolicyInEffect => _enforcedPolicyOptions.InEffect();
_enforcedPolicyOptions.UseLowercase || _enforcedPolicyOptions.UseNumbers ||
_enforcedPolicyOptions.NumberCount > 0 || _enforcedPolicyOptions.UseSpecial ||
_enforcedPolicyOptions.SpecialCount > 0;
public int TypeSelectedIndex public int TypeSelectedIndex
{ {

View File

@ -2,6 +2,7 @@
{ {
public class PasswordGeneratorPolicyOptions public class PasswordGeneratorPolicyOptions
{ {
public string DefaultType { get; set; }
public int MinLength { get; set; } public int MinLength { get; set; }
public bool UseUppercase { get; set; } public bool UseUppercase { get; set; }
public bool UseLowercase { get; set; } public bool UseLowercase { get; set; }
@ -9,5 +10,23 @@
public int NumberCount { get; set; } public int NumberCount { get; set; }
public bool UseSpecial { get; set; } public bool UseSpecial { get; set; }
public int SpecialCount { get; set; } public int SpecialCount { get; set; }
public int MinNumberOfWords { get; set; }
public bool Capitalize { get; set; }
public bool IncludeNumber { get; set; }
public bool InEffect()
{
return DefaultType != "" ||
MinLength > 0 ||
NumberCount > 0 ||
SpecialCount > 0 ||
UseUppercase ||
UseLowercase ||
UseNumbers ||
UseSpecial ||
MinNumberOfWords > 0 ||
Capitalize ||
IncludeNumber;
}
} }
} }

View File

@ -312,6 +312,27 @@ namespace Bit.Core.Services
{ {
options.MinSpecial = options.Length - options.MinNumber; options.MinSpecial = options.Length - options.MinNumber;
} }
if(options.NumWords < enforcedPolicyOptions.MinNumberOfWords)
{
options.NumWords = enforcedPolicyOptions.MinNumberOfWords;
}
if(enforcedPolicyOptions.Capitalize)
{
options.Capitalize = true;
}
if(enforcedPolicyOptions.IncludeNumber)
{
options.IncludeNumber = true;
}
// Force default type if password/passphrase selected via policy
if(enforcedPolicyOptions.DefaultType == "password" || enforcedPolicyOptions.DefaultType == "passphrase")
{
options.Type = enforcedPolicyOptions.DefaultType;
}
} }
else else
{ {
@ -344,6 +365,12 @@ namespace Bit.Core.Services
enforcedOptions = new PasswordGeneratorPolicyOptions(); enforcedOptions = new PasswordGeneratorPolicyOptions();
} }
var defaultType = GetPolicyString(currentPolicy, "defaultType");
if(defaultType != null && enforcedOptions.DefaultType != "password")
{
enforcedOptions.DefaultType = defaultType;
}
var minLength = GetPolicyInt(currentPolicy, "minLength"); var minLength = GetPolicyInt(currentPolicy, "minLength");
if(minLength != null && (int)(long)minLength > enforcedOptions.MinLength) if(minLength != null && (int)(long)minLength > enforcedOptions.MinLength)
{ {
@ -385,6 +412,24 @@ namespace Bit.Core.Services
{ {
enforcedOptions.SpecialCount = (int)(long)minSpecial; enforcedOptions.SpecialCount = (int)(long)minSpecial;
} }
var minNumberWords = GetPolicyInt(currentPolicy, "minNumberWords");
if(minNumberWords != null && (int)(long)minNumberWords > enforcedOptions.MinNumberOfWords)
{
enforcedOptions.MinNumberOfWords = (int)(long)minNumberWords;
}
var capitalize = GetPolicyBool(currentPolicy, "capitalize");
if(capitalize != null && (bool)capitalize)
{
enforcedOptions.Capitalize = true;
}
var includeNumber = GetPolicyBool(currentPolicy, "includeNumber");
if(includeNumber != null && (bool)includeNumber)
{
enforcedOptions.IncludeNumber = true;
}
} }
return enforcedOptions; return enforcedOptions;
@ -416,6 +461,19 @@ namespace Bit.Core.Services
return null; return null;
} }
private string GetPolicyString(Policy policy, string key)
{
if(policy.Data.ContainsKey(key))
{
var value = policy.Data[key];
if(value != null)
{
return (string)value;
}
}
return null;
}
public async Task SaveOptionsAsync(PasswordGenerationOptions options) public async Task SaveOptionsAsync(PasswordGenerationOptions options)
{ {
await _storageService.SaveAsync(Keys_Options, options); await _storageService.SaveAsync(Keys_Options, options);
@ -550,6 +608,11 @@ namespace Bit.Core.Services
options.NumWords = 20; options.NumWords = 20;
} }
if(options.NumWords < enforcedPolicyOptions.MinNumberOfWords)
{
options.NumWords = enforcedPolicyOptions.MinNumberOfWords;
}
if(options.WordSeparator != null && options.WordSeparator.Length > 1) if(options.WordSeparator != null && options.WordSeparator.Length > 1)
{ {
options.WordSeparator = options.WordSeparator[0].ToString(); options.WordSeparator = options.WordSeparator[0].ToString();