1
Fork 0
galene/group/client.go

128 lines
2.7 KiB
Go
Raw Normal View History

package group
import (
2020-11-29 14:26:42 +01:00
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"hash"
2024-04-30 18:17:00 +02:00
"net"
2020-11-29 14:26:42 +01:00
"golang.org/x/crypto/bcrypt"
2020-11-29 14:26:42 +01:00
"golang.org/x/crypto/pbkdf2"
2020-12-06 19:43:17 +01:00
2020-12-19 17:37:48 +01:00
"github.com/jech/galene/conn"
)
2020-11-29 14:26:42 +01:00
type RawPassword struct {
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"`
2020-11-29 14:26:42 +01:00
}
type Password RawPassword
func (p Password) Match(pw string) (bool, error) {
switch p.Type {
case "":
return false, nil
case "plain":
if p.Key == nil {
return false, errors.New("missing key")
}
return *p.Key == pw, nil
case "wildcard":
return true, nil
2020-11-29 14:26:42 +01:00
case "pbkdf2":
if p.Key == nil {
return false, errors.New("missing key")
}
key, err := hex.DecodeString(*p.Key)
2020-11-29 14:26:42 +01:00
if err != nil {
return false, err
}
salt, err := hex.DecodeString(p.Salt)
if err != nil {
return false, err
}
var h func() hash.Hash
switch p.Hash {
case "sha-256":
h = sha256.New
default:
return false, errors.New("unknown hash type")
}
theirKey := pbkdf2.Key(
[]byte(pw), salt, p.Iterations, len(key), h,
)
2022-04-23 18:22:28 +02:00
return bytes.Equal(key, theirKey), nil
case "bcrypt":
if p.Key == nil {
return false, errors.New("missing key")
}
err := bcrypt.CompareHashAndPassword([]byte(*p.Key), []byte(pw))
2024-05-27 23:00:45 +02:00
if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
return false, nil
}
return err == nil, err
2020-11-29 14:26:42 +01:00
default:
return false, errors.New("unknown password type")
}
}
func (p *Password) UnmarshalJSON(b []byte) error {
var k string
err := json.Unmarshal(b, &k)
if err == nil {
*p = Password{
Type: "plain",
Key: &k,
2020-11-29 14:26:42 +01:00
}
return nil
}
var r RawPassword
err = json.Unmarshal(b, &r)
if err == nil {
*p = Password(r)
}
return err
}
func (p Password) MarshalJSON() ([]byte, error) {
if p.Type == "plain" && p.Hash == "" && p.Salt == "" && p.Iterations == 0 {
2020-11-29 14:26:42 +01:00
return json.Marshal(p.Key)
}
return json.Marshal(RawPassword(p))
}
type ClientPattern struct {
2020-11-29 14:26:42 +01:00
Username string `json:"username,omitempty"`
Password *Password `json:"password,omitempty"`
}
type ClientCredentials struct {
System bool
Username *string
Password string
2021-10-29 23:37:05 +02:00
Token string
2020-11-29 14:26:42 +01:00
}
type Client interface {
Group() *Group
2024-04-30 18:17:00 +02:00
Addr() net.Addr
Id() string
Username() string
SetUsername(string)
Permissions() []string
SetPermissions([]string)
Data() map[string]interface{}
PushConn(g *Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error
RequestConns(target Client, g *Group, id string) error
Joined(group, kind string) error
PushClient(group, kind, id, username string, perms []string, data map[string]interface{}) error
Kick(id string, user *string, message string) error
}