security: remediate review B findings
This commit is contained in:
+21
-3
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
jwt "github.com/golang-jwt/jwt/v4"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type PermMask uint8
|
||||
@@ -86,8 +87,10 @@ func ParseRules(values []string) (*Manager, error) {
|
||||
}
|
||||
|
||||
func (m *Manager) Authenticate(user, pwd string) *Account {
|
||||
if a, ok := m.Accounts[user]; ok && (a.Enabled || a.PasswordHash == "") && (a.Password == pwd || a.PasswordHash == PasswordHash(pwd)) {
|
||||
return a
|
||||
if a, ok := m.Accounts[user]; ok && (a.Enabled || a.PasswordHash == "") {
|
||||
if a.Password == pwd || VerifyPasswordHash(a.PasswordHash, pwd) {
|
||||
return a
|
||||
}
|
||||
}
|
||||
if user == "" && pwd == "" {
|
||||
return m.Guest
|
||||
@@ -95,8 +98,23 @@ func (m *Manager) Authenticate(user, pwd string) *Account {
|
||||
return nil
|
||||
}
|
||||
func PasswordHash(password string) string {
|
||||
h, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return string(h)
|
||||
}
|
||||
|
||||
func VerifyPasswordHash(stored, password string) bool {
|
||||
if stored == "" {
|
||||
return false
|
||||
}
|
||||
if strings.HasPrefix(stored, "$2a$") || strings.HasPrefix(stored, "$2b$") || strings.HasPrefix(stored, "$2y$") {
|
||||
return bcrypt.CompareHashAndPassword([]byte(stored), []byte(password)) == nil
|
||||
}
|
||||
// Legacy unsalted SHA-256 hashes remain readable for one migration cycle.
|
||||
h := sha256.Sum256([]byte(password))
|
||||
return hex.EncodeToString(h[:])
|
||||
return hex.EncodeToString(h[:]) == stored
|
||||
}
|
||||
|
||||
func (a *Account) MaskFor(path string) PermMask {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPasswordHashUsesBcryptAndVerifies(t *testing.T) {
|
||||
hash := PasswordHash("correct horse battery staple")
|
||||
if len(hash) < 4 || (hash[0:4] != "$2a$" && hash[0:4] != "$2b$") {
|
||||
t.Fatalf("hash=%q is not bcrypt", hash)
|
||||
}
|
||||
if !VerifyPasswordHash(hash, "correct horse battery staple") {
|
||||
t.Fatal("bcrypt password did not verify")
|
||||
}
|
||||
if VerifyPasswordHash(hash, "wrong") {
|
||||
t.Fatal("wrong password verified")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLegacySHA256PasswordStillVerifies(t *testing.T) {
|
||||
sum := sha256.Sum256([]byte("legacy-pass"))
|
||||
hash := hex.EncodeToString(sum[:])
|
||||
if !VerifyPasswordHash(hash, "legacy-pass") {
|
||||
t.Fatal("legacy hash did not verify")
|
||||
}
|
||||
if VerifyPasswordHash(hash, "wrong") {
|
||||
t.Fatal("wrong legacy password verified")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user