mirror of
https://github.com/jech/galene.git
synced 2024-11-22 16:45: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(
|
key := pbkdf2.Key(
|
||||||
[]byte(pw), salt, iterations, length, sha256.New,
|
[]byte(pw), salt, iterations, length, sha256.New,
|
||||||
)
|
)
|
||||||
|
encoded := hex.EncodeToString(key)
|
||||||
p = group.Password{
|
p = group.Password{
|
||||||
Type: "pbkdf2",
|
Type: "pbkdf2",
|
||||||
Hash: "sha-256",
|
Hash: "sha-256",
|
||||||
Key: hex.EncodeToString(key),
|
Key: &encoded,
|
||||||
Salt: hex.EncodeToString(salt),
|
Salt: hex.EncodeToString(salt),
|
||||||
Iterations: iterations,
|
Iterations: iterations,
|
||||||
}
|
}
|
||||||
|
@ -75,9 +76,10 @@ func main() {
|
||||||
log.Fatalf("Couldn't hash password: %v", err)
|
log.Fatalf("Couldn't hash password: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
k := string(key)
|
||||||
p = group.Password{
|
p = group.Password{
|
||||||
Type: "bcrypt",
|
Type: "bcrypt",
|
||||||
Key: string(key),
|
Key: &k,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Fatalf("Unknown hash type %v", algorithm)
|
log.Fatalf("Unknown hash type %v", algorithm)
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
type RawPassword struct {
|
type RawPassword struct {
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Hash string `json:"hash,omitempty"`
|
Hash string `json:"hash,omitempty"`
|
||||||
Key string `json:"key"`
|
Key *string `json:"key,omitempty"`
|
||||||
Salt string `json:"salt,omitempty"`
|
Salt string `json:"salt,omitempty"`
|
||||||
Iterations int `json:"iterations,omitempty"`
|
Iterations int `json:"iterations,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,17 @@ func (p Password) Match(pw string) (bool, error) {
|
||||||
case "":
|
case "":
|
||||||
return false, errors.New("missing password")
|
return false, errors.New("missing password")
|
||||||
case "plain":
|
case "plain":
|
||||||
return p.Key == pw, nil
|
if p.Key == nil {
|
||||||
|
return false, errors.New("missing key")
|
||||||
|
}
|
||||||
|
return *p.Key == pw, nil
|
||||||
case "wildcard":
|
case "wildcard":
|
||||||
return true, nil
|
return true, nil
|
||||||
case "pbkdf2":
|
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 {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -53,7 +59,10 @@ func (p Password) Match(pw string) (bool, error) {
|
||||||
)
|
)
|
||||||
return bytes.Equal(key, theirKey), nil
|
return bytes.Equal(key, theirKey), nil
|
||||||
case "bcrypt":
|
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 {
|
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
@ -69,7 +78,7 @@ func (p *Password) UnmarshalJSON(b []byte) error {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
*p = Password{
|
*p = Password{
|
||||||
Type: "plain",
|
Type: "plain",
|
||||||
Key: k,
|
Key: &k,
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,23 +7,28 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var key1 = ""
|
||||||
var pw1 = Password{
|
var pw1 = Password{
|
||||||
Type: "plain",
|
Type: "plain",
|
||||||
|
Key: &key1,
|
||||||
}
|
}
|
||||||
|
var key2 = "pass"
|
||||||
var pw2 = Password{
|
var pw2 = Password{
|
||||||
Type: "plain",
|
Type: "plain",
|
||||||
Key: "pass",
|
Key: &key2,
|
||||||
}
|
}
|
||||||
|
var key3 = "fe499504e8f144693fae828e8e371d50e019d0e4c84994fa03f7f445bd8a570a"
|
||||||
var pw3 = Password{
|
var pw3 = Password{
|
||||||
Type: "pbkdf2",
|
Type: "pbkdf2",
|
||||||
Hash: "sha-256",
|
Hash: "sha-256",
|
||||||
Key: "fe499504e8f144693fae828e8e371d50e019d0e4c84994fa03f7f445bd8a570a",
|
Key: &key3,
|
||||||
Salt: "bcc1717851030776",
|
Salt: "bcc1717851030776",
|
||||||
Iterations: 4096,
|
Iterations: 4096,
|
||||||
}
|
}
|
||||||
|
var key4 = "$2a$10$afOr2f33onT/nDFFyT3mbOq5FMSw1wWXfyTXQTBMbKvZpBkoD3Qwu"
|
||||||
var pw4 = Password{
|
var pw4 = Password{
|
||||||
Type: "bcrypt",
|
Type: "bcrypt",
|
||||||
Key: "$2a$10$afOr2f33onT/nDFFyT3mbOq5FMSw1wWXfyTXQTBMbKvZpBkoD3Qwu",
|
Key: &key4,
|
||||||
}
|
}
|
||||||
var pw5 = Password{}
|
var pw5 = Password{}
|
||||||
var pw6 = 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) {
|
func TestJSON(t *testing.T) {
|
||||||
plain, err := json.Marshal(pw2)
|
plain, err := json.Marshal(pw2)
|
||||||
if err != nil || string(plain) != `"pass"` {
|
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 {
|
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")
|
return errors.New("user description is not sanitised")
|
||||||
}
|
}
|
||||||
groups.mu.Lock()
|
groups.mu.Lock()
|
||||||
|
|
|
@ -216,16 +216,17 @@ func TestWritableGroups(t *testing.T) {
|
||||||
t.Errorf("UpdateUser: got %v", err)
|
t.Errorf("UpdateUser: got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pw := "pw"
|
||||||
err = SetUserPassword("test", "jch", Password{
|
err = SetUserPassword("test", "jch", Password{
|
||||||
Type: "",
|
Type: "",
|
||||||
Key: "pw",
|
Key: &pw,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("SetUserPassword: got %v", err)
|
t.Errorf("SetUserPassword: got %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
desc, err = GetDescription("test")
|
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",
|
t.Errorf("GetDescription: got %v %v, expected %v %v",
|
||||||
err, desc.Users["jch"].Password.Key, nil, "pw",
|
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
|
iterations := 4096
|
||||||
key := pbkdf2.Key(body, salt, iterations, 32, sha256.New)
|
key := pbkdf2.Key(body, salt, iterations, 32, sha256.New)
|
||||||
|
encoded := hex.EncodeToString(key)
|
||||||
pw := group.Password{
|
pw := group.Password{
|
||||||
Type: "pbkdf2",
|
Type: "pbkdf2",
|
||||||
Hash: "sha-256",
|
Hash: "sha-256",
|
||||||
Key: hex.EncodeToString(key),
|
Key: &encoded,
|
||||||
Salt: hex.EncodeToString(salt),
|
Salt: hex.EncodeToString(salt),
|
||||||
Iterations: iterations,
|
Iterations: iterations,
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ func TestApi(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Get user: %v", err)
|
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")
|
t.Errorf("User not sanitised properly")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue