From 3ad546c39fe15db578cb794a018398be34f943ca Mon Sep 17 00:00:00 2001 From: Vincent Salucci <26154748+vincentsalucci@users.noreply.github.com> Date: Wed, 18 Mar 2020 10:07:57 -0500 Subject: [PATCH] Password Generator Sanitize Length (#89) * Initial commit for length sanitization * Updated sanitize function * Updated type instantiation Co-authored-by: Vincent Salucci --- .../passwordGeneration.service.ts | 1 + .../password-generator.component.ts | 55 +------ src/services/passwordGeneration.service.ts | 137 ++++++++++++++---- 3 files changed, 113 insertions(+), 80 deletions(-) diff --git a/src/abstractions/passwordGeneration.service.ts b/src/abstractions/passwordGeneration.service.ts index aa4d514b57..7978b7339e 100644 --- a/src/abstractions/passwordGeneration.service.ts +++ b/src/abstractions/passwordGeneration.service.ts @@ -12,4 +12,5 @@ export abstract class PasswordGenerationService { addHistory: (password: string) => Promise; clear: () => Promise; passwordStrength: (password: string, userInputs?: string[]) => zxcvbn.ZXCVBNResult; + normalizeOptions: (options: any, enforcedPolicyOptions: PasswordGeneratorPolicyOptions) => void; } diff --git a/src/angular/components/password-generator.component.ts b/src/angular/components/password-generator.component.ts index 51f70bc8bf..7b4fb07305 100644 --- a/src/angular/components/password-generator.component.ts +++ b/src/angular/components/password-generator.component.ts @@ -80,8 +80,7 @@ export class PasswordGeneratorComponent implements OnInit { } private normalizeOptions() { - this.options.minLowercase = 0; - this.options.minUppercase = 0; + // Application level normalize options depedent on class variables this.options.ambiguous = !this.avoidAmbiguous; if (!this.options.uppercase && !this.options.lowercase && !this.options.number && !this.options.special) { @@ -94,56 +93,6 @@ export class PasswordGeneratorComponent implements OnInit { } } - if (!this.options.length || this.options.length < 5) { - this.options.length = 5; - } else if (this.options.length > 128) { - this.options.length = 128; - } - - if (this.options.length < this.enforcedPolicyOptions.minLength) { - this.options.length = this.enforcedPolicyOptions.minLength; - } - - if (!this.options.minNumber) { - this.options.minNumber = 0; - } else if (this.options.minNumber > this.options.length) { - this.options.minNumber = this.options.length; - } else if (this.options.minNumber > 9) { - this.options.minNumber = 9; - } - - if (this.options.minNumber < this.enforcedPolicyOptions.numberCount) { - this.options.minNumber = this.enforcedPolicyOptions.numberCount; - } - - if (!this.options.minSpecial) { - this.options.minSpecial = 0; - } else if (this.options.minSpecial > this.options.length) { - this.options.minSpecial = this.options.length; - } else if (this.options.minSpecial > 9) { - this.options.minSpecial = 9; - } - - if (this.options.minSpecial < this.enforcedPolicyOptions.specialCount) { - this.options.minSpecial = this.enforcedPolicyOptions.specialCount; - } - - if (this.options.minSpecial + this.options.minNumber > this.options.length) { - this.options.minSpecial = this.options.length - this.options.minNumber; - } - - if (this.options.numWords == null || this.options.length < 3) { - this.options.numWords = 3; - } else if (this.options.numWords > 20) { - this.options.numWords = 20; - } - - if (this.options.numWords < this.enforcedPolicyOptions.minNumberWords) { - this.options.numWords = this.enforcedPolicyOptions.minNumberWords; - } - - if (this.options.wordSeparator != null && this.options.wordSeparator.length > 1) { - this.options.wordSeparator = this.options.wordSeparator[0]; - } + this.passwordGenerationService.normalizeOptions(this.options, this.enforcedPolicyOptions); } } diff --git a/src/services/passwordGeneration.service.ts b/src/services/passwordGeneration.service.ts index 2af4c40ce5..4aff5a4223 100644 --- a/src/services/passwordGeneration.service.ts +++ b/src/services/passwordGeneration.service.ts @@ -57,33 +57,7 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr } // sanitize - if (o.uppercase && o.minUppercase <= 0) { - o.minUppercase = 1; - } else if (!o.uppercase) { - o.minUppercase = 0; - } - - if (o.lowercase && o.minLowercase <= 0) { - o.minLowercase = 1; - } else if (!o.lowercase) { - o.minLowercase = 0; - } - - if (o.number && o.minNumber <= 0) { - o.minNumber = 1; - } else if (!o.number) { - o.minNumber = 0; - } - - if (o.special && o.minSpecial <= 0) { - o.minSpecial = 1; - } else if (!o.special) { - o.minSpecial = 0; - } - - if (!o.length || o.length < 1) { - o.length = 10; - } + this.sanitizePasswordLength(o, true); const minLength: number = o.minUppercase + o.minLowercase + o.minNumber + o.minSpecial; if (o.length < minLength) { @@ -419,6 +393,65 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr return result; } + normalizeOptions(options: any, enforcedPolicyOptions: PasswordGeneratorPolicyOptions) { + options.minLowercase = 0; + options.minUppercase = 0; + + if (!options.length || options.length < 5) { + options.length = 5; + } else if (options.length > 128) { + options.length = 128; + } + + if (options.length < enforcedPolicyOptions.minLength) { + options.length = enforcedPolicyOptions.minLength; + } + + if (!options.minNumber) { + options.minNumber = 0; + } else if (options.minNumber > options.length) { + options.minNumber = options.length; + } else if (options.minNumber > 9) { + options.minNumber = 9; + } + + if (options.minNumber < enforcedPolicyOptions.numberCount) { + options.minNumber = enforcedPolicyOptions.numberCount; + } + + if (!options.minSpecial) { + options.minSpecial = 0; + } else if (options.minSpecial > options.length) { + options.minSpecial = options.length; + } else if (options.minSpecial > 9) { + options.minSpecial = 9; + } + + if (options.minSpecial < enforcedPolicyOptions.specialCount) { + options.minSpecial = enforcedPolicyOptions.specialCount; + } + + if (options.minSpecial + options.minNumber > options.length) { + options.minSpecial = options.length - options.minNumber; + } + + if (options.numWords == null || options.length < 3) { + options.numWords = 3; + } else if (options.numWords > 20) { + options.numWords = 20; + } + + if (options.numWords < enforcedPolicyOptions.minNumberWords) { + options.numWords = enforcedPolicyOptions.minNumberWords; + } + + if (options.wordSeparator != null && options.wordSeparator.length > 1) { + options.wordSeparator = options.wordSeparator[0]; + } + + this.sanitizePasswordLength(options, false); + } + private capitalize(str: string) { return str.charAt(0).toUpperCase() + str.slice(1); } @@ -473,4 +506,54 @@ export class PasswordGenerationService implements PasswordGenerationServiceAbstr [array[i], array[j]] = [array[j], array[i]]; } } + + private sanitizePasswordLength(options: any, forGeneration: boolean) { + let minUppercaseCalc = 0; + let minLowercaseCalc = 0; + let minNumberCalc: number = options.minNumber; + let minSpecialCalc: number = options.minSpecial; + + if (options.uppercase && options.minUppercase <= 0) { + minUppercaseCalc = 1; + } else if (!options.uppercase) { + minUppercaseCalc = 0; + } + + if (options.lowercase && options.minLowercase <= 0) { + minLowercaseCalc = 1; + } else if (!options.lowercase) { + minLowercaseCalc = 0; + } + + if (options.number && options.minNumber <= 0) { + minNumberCalc = 1; + } else if (!options.number) { + minNumberCalc = 0; + } + + if (options.special && options.minSpecial <= 0) { + minSpecialCalc = 1; + } else if (!options.special) { + minSpecialCalc = 0; + } + + // This should never happen but is a final safety net + if (!options.length || options.length < 1) { + options.length = 10; + } + + const minLength: number = minUppercaseCalc + minLowercaseCalc + minNumberCalc + minSpecialCalc; + // Normalize and Generation both require this modification + if (options.length < minLength) { + options.length = minLength; + } + + // Apply other changes if the options object passed in is for generation + if (forGeneration) { + options.minUppercase = minUppercaseCalc; + options.minLowercase = minLowercaseCalc; + options.minNumber = minNumberCalc; + options.minSpecial = minSpecialCalc; + } + } }