1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-12-22 23:35:46 +01:00
galene/group/client.go
Juliusz Chroboczek 515c4a5cd0 Rename pushConns to requestConns, move into Client interface.
Also allow selecting just a single connection.
2021-05-14 23:21:14 +02:00

107 lines
2.3 KiB
Go

package group
import (
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"hash"
"golang.org/x/crypto/pbkdf2"
"github.com/jech/galene/conn"
)
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 Password RawPassword
func (p Password) Match(pw string) (bool, error) {
switch p.Type {
case "":
return p.Key == pw, nil
case "pbkdf2":
key, err := hex.DecodeString(p.Key)
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,
)
return bytes.Compare(key, theirKey) == 0, nil
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{
Key: k,
}
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 == "" && p.Hash == "" && p.Salt == "" && p.Iterations == 0 {
return json.Marshal(p.Key)
}
return json.Marshal(RawPassword(p))
}
type ClientCredentials struct {
Username string `json:"username,omitempty"`
Password *Password `json:"password,omitempty"`
}
type ClientPermissions struct {
Op bool `json:"op,omitempty"`
Present bool `json:"present,omitempty"`
Record bool `json:"record,omitempty"`
}
type Challengeable interface {
Username() string
Challenge(string, ClientCredentials) bool
}
type Client interface {
Group() *Group
Id() string
Challengeable
Permissions() ClientPermissions
SetPermissions(ClientPermissions)
Status() map[string]interface{}
OverridePermissions(*Group) bool
PushConn(g *Group, id string, conn conn.Up, tracks []conn.UpTrack, replace string) error
RequestConns(target Client, g *Group, id string) error
PushClient(id, username string, permissions *ClientPermissions, status map[string]interface{}, kind string) error
Kick(id, user, message string) error
}