code.gitea.io/gitea@v1.22.3/modules/auth/password/pwn/pwn_test.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package pwn 5 6 import ( 7 "math/rand" 8 "net/http" 9 "os" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/stretchr/testify/assert" 15 ) 16 17 var client = New(WithHTTP(&http.Client{ 18 Timeout: time.Second * 2, 19 })) 20 21 func TestMain(m *testing.M) { 22 rand.Seed(time.Now().Unix()) 23 os.Exit(m.Run()) 24 } 25 26 func TestPassword(t *testing.T) { 27 // Check input error 28 _, err := client.CheckPassword("", false) 29 assert.ErrorIs(t, err, ErrEmptyPassword, "blank input should return ErrEmptyPassword") 30 31 // Should fail 32 fail := "password1234" 33 count, err := client.CheckPassword(fail, false) 34 assert.NotEmpty(t, count, "%s should fail as a password", fail) 35 assert.NoError(t, err) 36 37 // Should fail (with padding) 38 failPad := "administrator" 39 count, err = client.CheckPassword(failPad, true) 40 assert.NotEmpty(t, count, "%s should fail as a password", failPad) 41 assert.NoError(t, err) 42 43 // Checking for a "good" password isn't going to be perfect, but we can give it a good try 44 // with hopefully minimal error. Try five times? 45 assert.Condition(t, func() bool { 46 for i := 0; i <= 5; i++ { 47 count, err = client.CheckPassword(testPassword(), false) 48 assert.NoError(t, err) 49 if count == 0 { 50 return true 51 } 52 } 53 return false 54 }, "no generated passwords passed. there is a chance this is a fluke") 55 56 // Again, but with padded responses 57 assert.Condition(t, func() bool { 58 for i := 0; i <= 5; i++ { 59 count, err = client.CheckPassword(testPassword(), true) 60 assert.NoError(t, err) 61 if count == 0 { 62 return true 63 } 64 } 65 return false 66 }, "no generated passwords passed. there is a chance this is a fluke") 67 } 68 69 // Credit to https://golangbyexample.com/generate-random-password-golang/ 70 // DO NOT USE THIS FOR AN ACTUAL PASSWORD GENERATOR 71 var ( 72 lowerCharSet = "abcdedfghijklmnopqrst" 73 upperCharSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 74 specialCharSet = "!@#$%&*" 75 numberSet = "0123456789" 76 allCharSet = lowerCharSet + upperCharSet + specialCharSet + numberSet 77 ) 78 79 func testPassword() string { 80 var password strings.Builder 81 82 // Set special character 83 for i := 0; i < 5; i++ { 84 random := rand.Intn(len(specialCharSet)) 85 password.WriteString(string(specialCharSet[random])) 86 } 87 88 // Set numeric 89 for i := 0; i < 5; i++ { 90 random := rand.Intn(len(numberSet)) 91 password.WriteString(string(numberSet[random])) 92 } 93 94 // Set uppercase 95 for i := 0; i < 5; i++ { 96 random := rand.Intn(len(upperCharSet)) 97 password.WriteString(string(upperCharSet[random])) 98 } 99 100 for i := 0; i < 5; i++ { 101 random := rand.Intn(len(allCharSet)) 102 password.WriteString(string(allCharSet[random])) 103 } 104 inRune := []rune(password.String()) 105 rand.Shuffle(len(inRune), func(i, j int) { 106 inRune[i], inRune[j] = inRune[j], inRune[i] 107 }) 108 return string(inRune) 109 }