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
This commit is contained in:
parent
898fe9d01e
commit
08d5e2e0d8
136
common/utils.go
136
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)
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue