mirror of
https://github.com/jech/galene.git
synced 2024-11-22 08:35:57 +01:00
Distinguish between no username and empty username.
This commit is contained in:
parent
a1c1345719
commit
aa53b78b2c
6 changed files with 66 additions and 46 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
|
|
|
@ -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,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue