1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-11-10 02:35:58 +01:00

Distinguish between no username and empty username.

This commit is contained in:
Juliusz Chroboczek 2023-03-22 17:41:16 +01:00
parent a1c1345719
commit aa53b78b2c
6 changed files with 66 additions and 46 deletions

View file

@ -101,7 +101,7 @@ func (client *Client) Close() error {
return nil return nil
} }
func (client *Client) Kick(id, user, message string) error { func (client *Client) Kick(id string, user *string, message string) error {
err := client.Close() err := client.Close()
group.DelClient(client) group.DelClient(client)
return err return err

View file

@ -83,7 +83,7 @@ type ClientPattern struct {
type ClientCredentials struct { type ClientCredentials struct {
System bool System bool
Username string Username *string
Password string Password string
Token string Token string
} }
@ -100,5 +100,5 @@ type Client interface {
RequestConns(target Client, g *Group, id string) error RequestConns(target Client, g *Group, id string) error
Joined(group, kind string) error Joined(group, kind string) error
PushClient(group, kind, id, username string, perms []string, data map[string]interface{}) error PushClient(group, kind, id, username string, perms []string, data map[string]interface{}) error
Kick(id, user, message string) error Kick(id string, user *string, message string) error
} }

View file

@ -36,7 +36,7 @@ func (err UserError) Error() string {
type KickError struct { type KickError struct {
Id string Id string
Username string Username *string
Message string Message string
} }
@ -45,8 +45,8 @@ func (err KickError) Error() string {
if err.Message != "" { if err.Message != "" {
m += " (" + err.Message + ")" m += " (" + err.Message + ")"
} }
if err.Username != "" { if err.Username != nil && *err.Username != "" {
m += " by " + err.Username m += " by " + *err.Username
} }
return m return m
} }
@ -59,7 +59,7 @@ func (err ProtocolError) Error() string {
type ChatHistoryEntry struct { type ChatHistoryEntry struct {
Id string Id string
User string User *string
Time time.Time Time time.Time
Kind string Kind string
Value interface{} Value interface{}
@ -625,9 +625,8 @@ func AddClient(group string, c Client, creds ClientCredentials) (*Group, error)
c.PushClient(g.Name(), "add", c.Id(), u, p, s) c.PushClient(g.Name(), "add", c.Id(), u, p, s)
for _, cc := range clients { for _, cc := range clients {
pp := cc.Permissions() pp := cc.Permissions()
c.PushClient( uu := cc.Username()
g.Name(), "add", cc.Id(), cc.Username(), pp, cc.Data(), c.PushClient(g.Name(), "add", cc.Id(), uu, pp, cc.Data())
)
cc.PushClient(g.Name(), "add", id, u, p, s) cc.PushClient(g.Name(), "add", id, u, p, s)
} }
@ -679,7 +678,7 @@ func DelClient(c Client) {
c.Joined(g.Name(), "leave") c.Joined(g.Name(), "leave")
for _, cc := range clients { for _, cc := range clients {
cc.PushClient( cc.PushClient(
g.Name(), "delete", c.Id(), "", nil, nil, g.Name(), "delete", c.Id(), c.Username(), nil, nil,
) )
} }
autoLockKick(g) autoLockKick(g)
@ -729,7 +728,7 @@ func (g *Group) Range(f func(c Client) bool) {
func kickall(g *Group, message string) { func kickall(g *Group, message string) {
g.Range(func(c Client) bool { g.Range(func(c Client) bool {
c.Kick("", "", message) c.Kick("", nil, message)
return true return true
}) })
} }
@ -768,7 +767,7 @@ func (g *Group) ClearChatHistory() {
g.history = nil g.history = nil
} }
func (g *Group) AddToChatHistory(id, user string, time time.Time, kind string, value interface{}) { func (g *Group) AddToChatHistory(id string, user *string, time time.Time, kind string, value interface{}) {
g.mu.Lock() g.mu.Lock()
defer g.mu.Unlock() defer g.mu.Unlock()
@ -810,9 +809,14 @@ func (g *Group) GetChatHistory() []ChatHistoryEntry {
} }
func matchClient(creds ClientCredentials, users []ClientPattern) (bool, bool) { func matchClient(creds ClientCredentials, users []ClientPattern) (bool, bool) {
if creds.Username == nil {
return false, false
}
username := *creds.Username
matched := false matched := false
for _, u := range users { for _, u := range users {
if u.Username == creds.Username { if u.Username == username {
matched = true matched = true
if u.Password == nil { if u.Password == nil {
return true, true return true, true
@ -1102,7 +1106,10 @@ func readDescription(name string) (*Description, error) {
func (g *Group) getPasswordPermission(creds ClientCredentials) ([]string, error) { func (g *Group) getPasswordPermission(creds ClientCredentials) ([]string, error) {
desc := g.description desc := g.description
if !desc.AllowAnonymous && creds.Username == "" { if creds.Username == nil {
return nil, errors.New("username not provided")
}
if !desc.AllowAnonymous && *creds.Username == "" {
return nil, ErrAnonymousNotAuthorised return nil, ErrAnonymousNotAuthorised
} }
if found, good := matchClient(creds, desc.Op); found { if found, good := matchClient(creds, desc.Op); found {
@ -1146,17 +1153,19 @@ func (g *Group) getPermission(creds ClientCredentials) (string, []string, error)
} }
username, perms, err = username, perms, err =
tok.Check(conf.CanonicalHost, g.name, &creds.Username) tok.Check(conf.CanonicalHost, g.name, creds.Username)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
} else { } else if creds.Username != nil {
username = *creds.Username
var err error var err error
username = creds.Username
perms, err = g.getPasswordPermission(creds) perms, err = g.getPasswordPermission(creds)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
} else {
return "", nil, errors.New("neither username nor token provided")
} }
return username, perms, nil return username, perms, nil

View file

@ -51,8 +51,9 @@ func TestChatHistory(t *testing.T) {
g := Group{ g := Group{
description: &Description{}, description: &Description{},
} }
user := "user"
for i := 0; i < 2*maxChatHistory; i++ { for i := 0; i < 2*maxChatHistory; i++ {
g.AddToChatHistory("id", "user", time.Now(), "", g.AddToChatHistory("id", &user, time.Now(), "",
fmt.Sprintf("%v", i), fmt.Sprintf("%v", i),
) )
} }
@ -108,10 +109,15 @@ func TestDescriptionJSON(t *testing.T) {
} }
} }
var jch = "jch"
var john = "john"
var james = "james"
var paul = "paul"
var badClients = []ClientCredentials{ var badClients = []ClientCredentials{
{Username: "jch", Password: "foo"}, {Username: &jch, Password: "foo"},
{Username: "john", Password: "foo"}, {Username: &john, Password: "foo"},
{Username: "james", Password: "foo"}, {Username: &james, Password: "foo"},
} }
type credPerm struct { type credPerm struct {
@ -121,23 +127,23 @@ type credPerm struct {
var goodClients = []credPerm{ var goodClients = []credPerm{
{ {
ClientCredentials{Username: "jch", Password: "topsecret"}, ClientCredentials{Username: &jch, Password: "topsecret"},
[]string{"op", "present"}, []string{"op", "present"},
}, },
{ {
ClientCredentials{Username: "john", Password: "secret"}, ClientCredentials{Username: &john, Password: "secret"},
[]string{"present"}, []string{"present"},
}, },
{ {
ClientCredentials{Username: "john", Password: "secret2"}, ClientCredentials{Username: &john, Password: "secret2"},
[]string{"present"}, []string{"present"},
}, },
{ {
ClientCredentials{Username: "james", Password: "secret3"}, ClientCredentials{Username: &james, Password: "secret3"},
nil, nil,
}, },
{ {
ClientCredentials{Username: "paul", Password: "secret3"}, ClientCredentials{Username: &paul, Password: "secret3"},
nil, nil,
}, },
} }
@ -150,7 +156,7 @@ func TestPermissions(t *testing.T) {
} }
for _, c := range badClients { for _, c := range badClients {
t.Run("bad "+c.Username, func(t *testing.T) { t.Run("bad "+*c.Username, func(t *testing.T) {
_, p, err := g.GetPermission(c) _, p, err := g.GetPermission(c)
if err != ErrNotAuthorised { if err != ErrNotAuthorised {
t.Errorf("GetPermission %v: %v %v", c, err, p) t.Errorf("GetPermission %v: %v %v", c, err, p)
@ -159,11 +165,11 @@ func TestPermissions(t *testing.T) {
} }
for _, cp := range goodClients { for _, cp := range goodClients {
t.Run("good "+cp.c.Username, func(t *testing.T) { t.Run("good "+*cp.c.Username, func(t *testing.T) {
u, p, err := g.GetPermission(cp.c) u, p, err := g.GetPermission(cp.c)
if err != nil { if err != nil {
t.Errorf("GetPermission %v: %v", cp.c, err) t.Errorf("GetPermission %v: %v", cp.c, err)
} else if u != cp.c.Username || } else if u != *cp.c.Username ||
!reflect.DeepEqual(p, cp.p) { !reflect.DeepEqual(p, cp.p) {
t.Errorf("%v: got %v %v, expected %v", t.Errorf("%v: got %v %v, expected %v",
cp.c, u, p, cp.p) cp.c, u, p, cp.p)

View file

@ -102,7 +102,7 @@ func (c *webClient) SetPermissions(perms []string) {
c.permissions = perms c.permissions = perms
} }
func (c *webClient) PushClient(group, kind, id, username string, perms []string, data map[string]interface{}) error { func (c *webClient) PushClient(group, kind, id string, username string, perms []string, data map[string]interface{}) error {
return c.action(pushClientAction{ return c.action(pushClientAction{
group, kind, id, username, perms, data, group, kind, id, username, perms, data,
}) })
@ -117,7 +117,7 @@ type clientMessage struct {
Replace string `json:"replace,omitempty"` Replace string `json:"replace,omitempty"`
Source string `json:"source,omitempty"` Source string `json:"source,omitempty"`
Dest string `json:"dest,omitempty"` Dest string `json:"dest,omitempty"`
Username string `json:"username,omitempty"` Username *string `json:"username,omitempty"`
Password string `json:"password,omitempty"` Password string `json:"password,omitempty"`
Token string `json:"token,omitempty"` Token string `json:"token,omitempty"`
Privileged bool `json:"privileged,omitempty"` Privileged bool `json:"privileged,omitempty"`
@ -555,7 +555,7 @@ func negotiate(c *webClient, down *rtpDownConnection, restartIce bool, replace s
Label: down.remote.Label(), Label: down.remote.Label(),
Replace: replace, Replace: replace,
Source: source, Source: source,
Username: username, Username: &username,
SDP: down.pc.LocalDescription().SDP, SDP: down.pc.LocalDescription().SDP,
}) })
} }
@ -930,7 +930,7 @@ type joinedAction struct {
type kickAction struct { type kickAction struct {
id string id string
username string username *string
message string message string
} }
@ -1160,11 +1160,12 @@ func handleAction(c *webClient, a interface{}) error {
return nil return nil
} }
perms := append([]string(nil), a.permissions...) perms := append([]string(nil), a.permissions...)
username := a.username
return c.write(clientMessage{ return c.write(clientMessage{
Type: "user", Type: "user",
Kind: a.kind, Kind: a.kind,
Id: a.id, Id: a.id,
Username: a.username, Username: &username,
Permissions: perms, Permissions: perms,
Data: a.data, Data: a.data,
}) })
@ -1181,11 +1182,12 @@ func handleAction(c *webClient, a interface{}) error {
} }
} }
perms := append([]string(nil), c.permissions...) perms := append([]string(nil), c.permissions...)
username := c.username
err := c.write(clientMessage{ err := c.write(clientMessage{
Type: "joined", Type: "joined",
Kind: a.kind, Kind: a.kind,
Group: a.group, Group: a.group,
Username: c.username, Username: &username,
Permissions: perms, Permissions: perms,
Status: status, Status: status,
Data: data, Data: data,
@ -1222,11 +1224,12 @@ func handleAction(c *webClient, a interface{}) error {
} }
perms := append([]string(nil), c.permissions...) perms := append([]string(nil), c.permissions...)
status := g.Status(true, "") status := g.Status(true, "")
username := c.username
c.write(clientMessage{ c.write(clientMessage{
Type: "joined", Type: "joined",
Kind: "change", Kind: "change",
Group: g.Name(), Group: g.Name(),
Username: c.username, Username: &username,
Permissions: perms, Permissions: perms,
Status: &status, Status: &status,
RTCConfiguration: ice.ICEConfiguration(), RTCConfiguration: ice.ICEConfiguration(),
@ -1360,7 +1363,7 @@ func setPermissions(g *group.Group, id string, perm string) error {
return c.action(permissionsChangedAction{}) return c.action(permissionsChangedAction{})
} }
func (c *webClient) Kick(id, user, message string) error { func (c *webClient) Kick(id string, user *string, message string) error {
return c.action(kickAction{id, user, message}) return c.action(kickAction{id, user, message})
} }
@ -1368,7 +1371,7 @@ func (c *webClient) Joined(group, kind string) error {
return c.action(joinedAction{group, kind}) return c.action(joinedAction{group, kind})
} }
func kickClient(g *group.Group, id, user, dest string, message string) error { func kickClient(g *group.Group, id string, user *string, dest string, message string) error {
client := g.GetClient(dest) client := g.GetClient(dest)
if client == nil { if client == nil {
return group.UserError("no such user") return group.UserError("no such user")
@ -1385,8 +1388,8 @@ func handleClientMessage(c *webClient, m clientMessage) error {
} }
if m.Type != "join" { if m.Type != "join" {
if m.Username != "" { if m.Username != nil {
if m.Username != c.Username() { if *m.Username != c.Username() {
return group.ProtocolError("spoofed username") return group.ProtocolError("spoofed username")
} }
} }
@ -1411,7 +1414,6 @@ func handleClientMessage(c *webClient, m clientMessage) error {
"cannot join multiple groups", "cannot join multiple groups",
) )
} }
c.username = m.Username
c.data = m.Data c.data = m.Data
g, err := group.AddClient(m.Group, c, g, err := group.AddClient(m.Group, c,
group.ClientCredentials{ group.ClientCredentials{
@ -1435,23 +1437,25 @@ func handleClientMessage(c *webClient, m clientMessage) error {
s = "internal server error" s = "internal server error"
log.Printf("Join group: %v", err) log.Printf("Join group: %v", err)
} }
username := c.username
return c.write(clientMessage{ return c.write(clientMessage{
Type: "joined", Type: "joined",
Kind: "fail", Kind: "fail",
Error: e, Error: e,
Group: m.Group, Group: m.Group,
Username: c.username, Username: &username,
Value: s, Value: s,
}) })
} }
if redirect := g.Description().Redirect; redirect != "" { if redirect := g.Description().Redirect; redirect != "" {
// We normally redirect at the HTTP level, but the group // We normally redirect at the HTTP level, but the group
// description could have been edited in the meantime. // description could have been edited in the meantime.
username := c.username
return c.write(clientMessage{ return c.write(clientMessage{
Type: "joined", Type: "joined",
Kind: "redirect", Kind: "redirect",
Group: m.Group, Group: m.Group,
Username: c.username, Username: &username,
Value: redirect, Value: redirect,
}) })
} }
@ -1677,10 +1681,11 @@ func handleClientMessage(c *webClient, m clientMessage) error {
s = s + fmt.Sprintf("%v (%v client%v)\n", s = s + fmt.Sprintf("%v (%v client%v)\n",
sg.Name, sg.Clients, plural) sg.Name, sg.Clients, plural)
} }
username := "Server"
c.write(clientMessage{ c.write(clientMessage{
Type: "chat", Type: "chat",
Dest: c.id, Dest: c.id,
Username: "Server", Username: &username,
Time: time.Now().Format(time.RFC3339), Time: time.Now().Format(time.RFC3339),
Value: s, Value: s,
}) })

View file

@ -642,7 +642,7 @@ func checkGroupPermissions(w http.ResponseWriter, r *http.Request, groupname str
_, p, err := g.GetPermission( _, p, err := g.GetPermission(
group.ClientCredentials{ group.ClientCredentials{
Username: user, Username: &user,
Password: pass, Password: pass,
}, },
) )