From 08d5e2e0d8229952bd3c97b8aaee73b2a0ee71e6 Mon Sep 17 00:00:00 2001 From: Azareal Date: Thu, 18 Jun 2020 12:39:21 +1000 Subject: [PATCH] add more weak password definitions move the weak password logic to it's own file add another weak password test case and split the test function --- common/utils.go | 136 --------------------------------- common/weak_passwords.go | 143 +++++++++++++++++++++++++++++++++++ config/weakpass_default.json | 4 +- misc_test.go | 7 +- 4 files changed, 150 insertions(+), 140 deletions(-) create mode 100644 common/weak_passwords.go diff --git a/common/utils.go b/common/utils.go index db48df58..6501a09b 100644 --- a/common/utils.go +++ b/common/utils.go @@ -381,142 +381,6 @@ func unmarshalJsonFileIgnore404(name string, in interface{}) error { return json.Unmarshal(data, in) } -type weakpassHolder struct { - Contains []string `json:"contains"` - Literal []string `json:"literal"` -} - -func InitWeakPasswords() error { - var weakpass weakpassHolder - err := unmarshalJsonFile("./config/weakpass_default.json", &weakpass) - if err != nil { - return err - } - - wcon := make(map[string]struct{}) - for _, item := range weakpass.Contains { - wcon[item] = struct{}{} - } - for _, item := range weakpass.Literal { - weakPassLit[item] = struct{}{} - } - - weakpass = weakpassHolder{} - err = unmarshalJsonFileIgnore404("./config/weakpass.json", &weakpass) - if err != nil { - return err - } - - for _, item := range weakpass.Contains { - wcon[item] = struct{}{} - } - for _, item := range weakpass.Literal { - weakPassLit[item] = struct{}{} - } - weakPassStrings = make([]string, len(wcon)) - var i int - for pattern, _ := range wcon { - weakPassStrings[i] = pattern - i++ - } - - s := "You may not have " - for i, passBit := range weakPassStrings { - if i > 0 { - if i == len(weakPassStrings)-1 { - s += " or " - } else { - s += ", " - } - } - s += "'" + passBit + "'" - } - ErrWeakPasswordContains = errors.New(s + " in your password") - - return nil -} - -var weakPassStrings []string -var weakPassLit = make(map[string]struct{}) -var ErrWeakPasswordNone = errors.New("You didn't put in a password.") -var ErrWeakPasswordShort = errors.New("Your password needs to be at-least eight characters long") -var ErrWeakPasswordNameInPass = errors.New("You can't use your name in your password.") -var ErrWeakPasswordEmailInPass = errors.New("You can't use your email in your password.") -var ErrWeakPasswordCommon = errors.New("You may not use a password that is in common use") -var ErrWeakPasswordNoNumbers = errors.New("You don't have any numbers in your password") -var ErrWeakPasswordNoUpper = errors.New("You don't have any uppercase characters in your password") -var ErrWeakPasswordNoLower = errors.New("You don't have any lowercase characters in your password") -var ErrWeakPasswordUniqueChars = errors.New("You don't have enough unique characters in your password") -var ErrWeakPasswordContains error - -// TODO: Write a test for this -func WeakPassword(password, username, email string) error { - lowPassword := strings.ToLower(password) - switch { - case password == "": - return ErrWeakPasswordNone - case len(password) < 8: - return ErrWeakPasswordShort - case len(username) > 3 && strings.Contains(lowPassword, strings.ToLower(username)): - return ErrWeakPasswordNameInPass - case len(email) > 2 && strings.Contains(lowPassword, strings.ToLower(email)): - return ErrWeakPasswordEmailInPass - } - - _, ok := weakPassLit[lowPassword] - if ok { - return ErrWeakPasswordCommon - } - for _, passBit := range weakPassStrings { - if strings.Contains(lowPassword, passBit) { - return ErrWeakPasswordContains - } - } - - charMap := make(map[rune]int) - var numbers, symbols, upper, lower int - for _, char := range password { - charItem, ok := charMap[char] - if ok { - charItem++ - } else { - charItem = 1 - } - charMap[char] = charItem - - if unicode.IsLetter(char) { - if unicode.IsUpper(char) { - upper++ - } else { - lower++ - } - } else if unicode.IsNumber(char) { - numbers++ - } else { - symbols++ - } - } - - if upper == 0 { - return ErrWeakPasswordNoUpper - } - if lower == 0 { - return ErrWeakPasswordNoLower - } - if len(password) < 18 { - if numbers == 0 { - return ErrWeakPasswordNoNumbers - } - if (len(password) / 2) > len(charMap) { - return ErrWeakPasswordUniqueChars - } - } else if (len(password) / 3) > len(charMap) { - // Be a little lenient on the number of unique characters for long passwords - return ErrWeakPasswordUniqueChars - } - return nil -} - // TODO: Write a test for this func CanonEmail(email string) string { email = strings.ToLower(email) diff --git a/common/weak_passwords.go b/common/weak_passwords.go new file mode 100644 index 00000000..7666ab91 --- /dev/null +++ b/common/weak_passwords.go @@ -0,0 +1,143 @@ +package common + +import ( + "errors" + "strings" + "unicode" +) + +var weakPassStrings []string +var weakPassLit = make(map[string]struct{}) +var ErrWeakPasswordNone = errors.New("You didn't put in a password.") +var ErrWeakPasswordShort = errors.New("Your password needs to be at-least eight characters long") +var ErrWeakPasswordNameInPass = errors.New("You can't use your name in your password.") +var ErrWeakPasswordEmailInPass = errors.New("You can't use your email in your password.") +var ErrWeakPasswordCommon = errors.New("You may not use a password that is in common use") +var ErrWeakPasswordNoNumbers = errors.New("You don't have any numbers in your password") +var ErrWeakPasswordNoUpper = errors.New("You don't have any uppercase characters in your password") +var ErrWeakPasswordNoLower = errors.New("You don't have any lowercase characters in your password") +var ErrWeakPasswordUniqueChars = errors.New("You don't have enough unique characters in your password") +var ErrWeakPasswordContains error + +type weakpassHolder struct { + Contains []string `json:"contains"` + Literal []string `json:"literal"` +} + +func InitWeakPasswords() error { + var weakpass weakpassHolder + err := unmarshalJsonFile("./config/weakpass_default.json", &weakpass) + if err != nil { + return err + } + + wcon := make(map[string]struct{}) + for _, item := range weakpass.Contains { + wcon[item] = struct{}{} + } + for _, item := range weakpass.Literal { + weakPassLit[item] = struct{}{} + } + + weakpass = weakpassHolder{} + err = unmarshalJsonFileIgnore404("./config/weakpass.json", &weakpass) + if err != nil { + return err + } + + for _, item := range weakpass.Contains { + wcon[item] = struct{}{} + } + for _, item := range weakpass.Literal { + weakPassLit[item] = struct{}{} + } + weakPassStrings = make([]string, len(wcon)) + var i int + for pattern, _ := range wcon { + weakPassStrings[i] = pattern + i++ + } + + s := "You may not have " + for i, passBit := range weakPassStrings { + if i > 0 { + if i == len(weakPassStrings)-1 { + s += " or " + } else { + s += ", " + } + } + s += "'" + passBit + "'" + } + ErrWeakPasswordContains = errors.New(s + " in your password") + + return nil +} + +// TODO: Write a test for this +func WeakPassword(password, username, email string) error { + lowPassword := strings.ToLower(password) + switch { + case password == "": + return ErrWeakPasswordNone + case len(password) < 8: + return ErrWeakPasswordShort + case len(username) > 3 && strings.Contains(lowPassword, strings.ToLower(username)): + return ErrWeakPasswordNameInPass + case len(email) > 2 && strings.Contains(lowPassword, strings.ToLower(email)): + return ErrWeakPasswordEmailInPass + } + + _, ok := weakPassLit[lowPassword] + if ok { + return ErrWeakPasswordCommon + } + for _, passBit := range weakPassStrings { + if strings.Contains(lowPassword, passBit) { + return ErrWeakPasswordContains + } + } + + charMap := make(map[rune]int) + var numbers, symbols, upper, lower int + for _, char := range password { + charItem, ok := charMap[char] + if ok { + charItem++ + } else { + charItem = 1 + } + charMap[char] = charItem + + if unicode.IsLetter(char) { + if unicode.IsUpper(char) { + upper++ + } else { + lower++ + } + } else if unicode.IsNumber(char) { + numbers++ + } else { + symbols++ + } + } + + if upper == 0 { + return ErrWeakPasswordNoUpper + } + if lower == 0 { + return ErrWeakPasswordNoLower + } + if len(password) < 18 { + if numbers == 0 { + return ErrWeakPasswordNoNumbers + } + if (len(password) / 2) > len(charMap) { + return ErrWeakPasswordUniqueChars + } + } else if (len(password) / 3) > len(charMap) { + // Be a little lenient on the number of unique characters for long passwords + return ErrWeakPasswordUniqueChars + } + return nil +} diff --git a/config/weakpass_default.json b/config/weakpass_default.json index c673f4b2..c8f88508 100644 --- a/config/weakpass_default.json +++ b/config/weakpass_default.json @@ -1,8 +1,8 @@ { "contains":[ - "test", "123", "6969", "password", "qwerty", "fuck", "love" + "test", "123", "6969", "password", "qwerty", "fuck", "love","1 2 3 4 5" ], "literal":[ - "superman" + "superman","football","starwars","passw0rd","whatever","master's degree","trustno1","computer" ] } \ No newline at end of file diff --git a/misc_test.go b/misc_test.go index 952bb1aa..1af806a0 100644 --- a/misc_test.go +++ b/misc_test.go @@ -2038,6 +2038,10 @@ func TestUtils(t *testing.T) { cemail = c.CanonEmail(email) expect(t, cemail == lowEmail, fmt.Sprintf("%s should be %s", cemail, lowEmail)) + // TODO: More utils.go tests +} + +func TestWeakPassword(t *testing.T) { /*weakPass := func(password, username, email string) func(error,string,...interface{}) { err := c.WeakPassword(password, username, email) return func(expectErr error, m string, p ...interface{}) { @@ -2072,6 +2076,7 @@ func TestUtils(t *testing.T) { weakPass("test2", "draw", "test@example.com")(c.ErrWeakPasswordShort) weakPass("test22222222", "draw", "test@example.com")(c.ErrWeakPasswordContains) weakPass("superman", "draw", "test@example.com")(c.ErrWeakPasswordCommon) + weakPass("superman2", "draw", "test@example.com")(c.ErrWeakPasswordNoUpper) weakPass("K\\@<^s}1", "draw", "test@example.com")(nil) weakPass("K\\@<^s}r", "draw", "test@example.com")(c.ErrWeakPasswordNoNumbers) weakPass("k\\@<^s}1", "draw", "test@example.com")(c.ErrWeakPasswordNoUpper) @@ -2081,8 +2086,6 @@ func TestUtils(t *testing.T) { weakPass("11111111111111111111", "draw", "test@example.com")(c.ErrWeakPasswordNoUpper) weakPass("aaaaaaaaaaAAAAAAAAAA", "draw", "test@example.com")(c.ErrWeakPasswordUniqueChars) weakPass("-:u/nMxb,A!n=B;H\\sjM", "draw", "test@example.com")(nil) - - // TODO: More utils.go tests } func TestAuth(t *testing.T) {