mirror of
https://github.com/jech/galene.git
synced 2024-11-22 00:25:58 +01:00
Distinguish empty key in password from absence of key.
This commit is contained in:
parent
4ad7c2f303
commit
695c379a6c
7 changed files with 46 additions and 19 deletions
|
@ -60,10 +60,11 @@ func main() {
|
|||
key := pbkdf2.Key(
|
||||
[]byte(pw), salt, iterations, length, sha256.New,
|
||||
)
|
||||
encoded := hex.EncodeToString(key)
|
||||
p = group.Password{
|
||||
Type: "pbkdf2",
|
||||
Hash: "sha-256",
|
||||
Key: hex.EncodeToString(key),
|
||||
Key: &encoded,
|
||||
Salt: hex.EncodeToString(salt),
|
||||
Iterations: iterations,
|
||||
}
|
||||
|
@ -75,9 +76,10 @@ func main() {
|
|||
log.Fatalf("Couldn't hash password: %v", err)
|
||||
}
|
||||
|
||||
k := string(key)
|
||||
p = group.Password{
|
||||
Type: "bcrypt",
|
||||
Key: string(key),
|
||||
Key: &k,
|
||||
}
|
||||
} else {
|
||||
log.Fatalf("Unknown hash type %v", algorithm)
|
||||
|
|
|
@ -15,11 +15,11 @@ import (
|
|||
)
|
||||
|
||||
type RawPassword struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Hash string `json:"hash,omitempty"`
|
||||
Key string `json:"key"`
|
||||
Salt string `json:"salt,omitempty"`
|
||||
Iterations int `json:"iterations,omitempty"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Hash string `json:"hash,omitempty"`
|
||||
Key *string `json:"key,omitempty"`
|
||||
Salt string `json:"salt,omitempty"`
|
||||
Iterations int `json:"iterations,omitempty"`
|
||||
}
|
||||
|
||||
type Password RawPassword
|
||||
|
@ -29,11 +29,17 @@ func (p Password) Match(pw string) (bool, error) {
|
|||
case "":
|
||||
return false, errors.New("missing password")
|
||||
case "plain":
|
||||
return p.Key == pw, nil
|
||||
if p.Key == nil {
|
||||
return false, errors.New("missing key")
|
||||
}
|
||||
return *p.Key == pw, nil
|
||||
case "wildcard":
|
||||
return true, nil
|
||||
case "pbkdf2":
|
||||
key, err := hex.DecodeString(p.Key)
|
||||
if p.Key == nil {
|
||||
return false, errors.New("missing key")
|
||||
}
|
||||
key, err := hex.DecodeString(*p.Key)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
@ -53,7 +59,10 @@ func (p Password) Match(pw string) (bool, error) {
|
|||
)
|
||||
return bytes.Equal(key, theirKey), nil
|
||||
case "bcrypt":
|
||||
err := bcrypt.CompareHashAndPassword([]byte(p.Key), []byte(pw))
|
||||
if p.Key == nil {
|
||||
return false, errors.New("missing key")
|
||||
}
|
||||
err := bcrypt.CompareHashAndPassword([]byte(*p.Key), []byte(pw))
|
||||
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||
return false, nil
|
||||
}
|
||||
|
@ -69,7 +78,7 @@ func (p *Password) UnmarshalJSON(b []byte) error {
|
|||
if err == nil {
|
||||
*p = Password{
|
||||
Type: "plain",
|
||||
Key: k,
|
||||
Key: &k,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -7,23 +7,28 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
var key1 = ""
|
||||
var pw1 = Password{
|
||||
Type: "plain",
|
||||
Key: &key1,
|
||||
}
|
||||
var key2 = "pass"
|
||||
var pw2 = Password{
|
||||
Type: "plain",
|
||||
Key: "pass",
|
||||
Key: &key2,
|
||||
}
|
||||
var key3 = "fe499504e8f144693fae828e8e371d50e019d0e4c84994fa03f7f445bd8a570a"
|
||||
var pw3 = Password{
|
||||
Type: "pbkdf2",
|
||||
Hash: "sha-256",
|
||||
Key: "fe499504e8f144693fae828e8e371d50e019d0e4c84994fa03f7f445bd8a570a",
|
||||
Key: &key3,
|
||||
Salt: "bcc1717851030776",
|
||||
Iterations: 4096,
|
||||
}
|
||||
var key4 = "$2a$10$afOr2f33onT/nDFFyT3mbOq5FMSw1wWXfyTXQTBMbKvZpBkoD3Qwu"
|
||||
var pw4 = Password{
|
||||
Type: "bcrypt",
|
||||
Key: "$2a$10$afOr2f33onT/nDFFyT3mbOq5FMSw1wWXfyTXQTBMbKvZpBkoD3Qwu",
|
||||
Key: &key4,
|
||||
}
|
||||
var pw5 = Password{}
|
||||
var pw6 = Password{
|
||||
|
@ -66,6 +71,15 @@ func TestBad(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestEmptyKey(t *testing.T) {
|
||||
for _, tpe := range []string{"", "plain", "pbkdf2", "bcrypt", "bad"} {
|
||||
pw := Password{Type: tpe}
|
||||
if match, err := pw.Match(""); err == nil || match {
|
||||
t.Errorf("empty password of type %v didn't error", tpe)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSON(t *testing.T) {
|
||||
plain, err := json.Marshal(pw2)
|
||||
if err != nil || string(plain) != `"pass"` {
|
||||
|
|
|
@ -629,7 +629,7 @@ func DeleteUser(group, username, etag string) error {
|
|||
}
|
||||
|
||||
func UpdateUser(group, username, etag string, user *UserDescription) error {
|
||||
if user.Password.Type != "" || user.Password.Key != "" {
|
||||
if user.Password.Type != "" || user.Password.Key != nil {
|
||||
return errors.New("user description is not sanitised")
|
||||
}
|
||||
groups.mu.Lock()
|
||||
|
|
|
@ -216,16 +216,17 @@ func TestWritableGroups(t *testing.T) {
|
|||
t.Errorf("UpdateUser: got %v", err)
|
||||
}
|
||||
|
||||
pw := "pw"
|
||||
err = SetUserPassword("test", "jch", Password{
|
||||
Type: "",
|
||||
Key: "pw",
|
||||
Key: &pw,
|
||||
})
|
||||
if err != nil {
|
||||
t.Errorf("SetUserPassword: got %v", err)
|
||||
}
|
||||
|
||||
desc, err = GetDescription("test")
|
||||
if err != nil || desc.Users["jch"].Password.Key != "pw" {
|
||||
if err != nil || *desc.Users["jch"].Password.Key != "pw" {
|
||||
t.Errorf("GetDescription: got %v %v, expected %v %v",
|
||||
err, desc.Users["jch"].Password.Key, nil, "pw",
|
||||
)
|
||||
|
|
|
@ -408,10 +408,11 @@ func passwordHandler(w http.ResponseWriter, r *http.Request, g, user string) {
|
|||
}
|
||||
iterations := 4096
|
||||
key := pbkdf2.Key(body, salt, iterations, 32, sha256.New)
|
||||
encoded := hex.EncodeToString(key)
|
||||
pw := group.Password{
|
||||
Type: "pbkdf2",
|
||||
Hash: "sha-256",
|
||||
Key: hex.EncodeToString(key),
|
||||
Key: &encoded,
|
||||
Salt: hex.EncodeToString(salt),
|
||||
Iterations: iterations,
|
||||
}
|
||||
|
|
|
@ -236,7 +236,7 @@ func TestApi(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Errorf("Get user: %v", err)
|
||||
}
|
||||
if user.Password.Type != "" && user.Password.Key != "" {
|
||||
if user.Password.Type != "" && user.Password.Key != nil {
|
||||
t.Errorf("User not sanitised properly")
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue