Commit aa53b78b authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Distinguish between no username and empty username.

parent a1c13457
......@@ -101,7 +101,7 @@ func (client *Client) Close() error {
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()
group.DelClient(client)
return err
......
......@@ -83,7 +83,7 @@ type ClientPattern struct {
type ClientCredentials struct {
System bool
Username string
Username *string
Password string
Token string
}
......@@ -100,5 +100,5 @@ type Client interface {
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, user, message string) error
Kick(id string, user *string, message string) error
}
......@@ -36,7 +36,7 @@ func (err UserError) Error() string {
type KickError struct {
Id string
Username string
Username *string
Message string
}
......@@ -45,8 +45,8 @@ func (err KickError) Error() string {
if err.Message != "" {
m += " (" + err.Message + ")"
}
if err.Username != "" {
m += " by " + err.Username
if err.Username != nil && *err.Username != "" {
m += " by " + *err.Username
}
return m
}
......@@ -59,7 +59,7 @@ func (err ProtocolError) Error() string {
type ChatHistoryEntry struct {
Id string
User string
User *string
Time time.Time
Kind string
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)
for _, cc := range clients {
pp := cc.Permissions()
c.PushClient(
g.Name(), "add", cc.Id(), cc.Username(), pp, cc.Data(),
)
uu := cc.Username()
c.PushClient(g.Name(), "add", cc.Id(), uu, pp, cc.Data())
cc.PushClient(g.Name(), "add", id, u, p, s)
}
......@@ -679,7 +678,7 @@ func DelClient(c Client) {
c.Joined(g.Name(), "leave")
for _, cc := range clients {
cc.PushClient(
g.Name(), "delete", c.Id(), "", nil, nil,
g.Name(), "delete", c.Id(), c.Username(), nil, nil,
)
}
autoLockKick(g)
......@@ -729,7 +728,7 @@ func (g *Group) Range(f func(c Client) bool) {
func kickall(g *Group, message string) {
g.Range(func(c Client) bool {
c.Kick("", "", message)
c.Kick("", nil, message)
return true
})
}
......@@ -768,7 +767,7 @@ func (g *Group) ClearChatHistory() {
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()
defer g.mu.Unlock()
......@@ -810,9 +809,14 @@ func (g *Group) GetChatHistory() []ChatHistoryEntry {
}
func matchClient(creds ClientCredentials, users []ClientPattern) (bool, bool) {
if creds.Username == nil {
return false, false
}
username := *creds.Username
matched := false
for _, u := range users {
if u.Username == creds.Username {
if u.Username == username {
matched = true
if u.Password == nil {
return true, true
......@@ -1102,7 +1106,10 @@ func readDescription(name string) (*Description, error) {
func (g *Group) getPasswordPermission(creds ClientCredentials) ([]string, error) {
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
}
if found, good := matchClient(creds, desc.Op); found {
......@@ -1146,17 +1153,19 @@ func (g *Group) getPermission(creds ClientCredentials) (string, []string, error)
}
username, perms, err =
tok.Check(conf.CanonicalHost, g.name, &creds.Username)
tok.Check(conf.CanonicalHost, g.name, creds.Username)
if err != nil {
return "", nil, err
}
} else {
} else if creds.Username != nil {
username = *creds.Username
var err error
username = creds.Username
perms, err = g.getPasswordPermission(creds)
if err != nil {
return "", nil, err
}
} else {
return "", nil, errors.New("neither username nor token provided")
}
return username, perms, nil
......
......@@ -51,8 +51,9 @@ func TestChatHistory(t *testing.T) {
g := Group{
description: &Description{},
}
user := "user"
for i := 0; i < 2*maxChatHistory; i++ {
g.AddToChatHistory("id", "user", time.Now(), "",
g.AddToChatHistory("id", &user, time.Now(), "",
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{
{Username: "jch", Password: "foo"},
{Username: "john", Password: "foo"},
{Username: "james", Password: "foo"},
{Username: &jch, Password: "foo"},
{Username: &john, Password: "foo"},
{Username: &james, Password: "foo"},
}
type credPerm struct {
......@@ -121,23 +127,23 @@ type credPerm struct {
var goodClients = []credPerm{
{
ClientCredentials{Username: "jch", Password: "topsecret"},
ClientCredentials{Username: &jch, Password: "topsecret"},
[]string{"op", "present"},
},
{
ClientCredentials{Username: "john", Password: "secret"},
ClientCredentials{Username: &john, Password: "secret"},
[]string{"present"},
},
{
ClientCredentials{Username: "john", Password: "secret2"},
ClientCredentials{Username: &john, Password: "secret2"},
[]string{"present"},
},
{
ClientCredentials{Username: "james", Password: "secret3"},
ClientCredentials{Username: &james, Password: "secret3"},
nil,
},
{
ClientCredentials{Username: "paul", Password: "secret3"},
ClientCredentials{Username: &paul, Password: "secret3"},
nil,
},
}
......@@ -150,7 +156,7 @@ func TestPermissions(t *testing.T) {
}
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)
if err != ErrNotAuthorised {
t.Errorf("GetPermission %v: %v %v", c, err, p)
......@@ -159,11 +165,11 @@ func TestPermissions(t *testing.T) {
}
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)
if err != nil {
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) {
t.Errorf("%v: got %v %v, expected %v",
cp.c, u, p, cp.p)
......
......@@ -102,7 +102,7 @@ func (c *webClient) SetPermissions(perms []string) {
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{
group, kind, id, username, perms, data,
})
......@@ -117,7 +117,7 @@ type clientMessage struct {
Replace string `json:"replace,omitempty"`
Source string `json:"source,omitempty"`
Dest string `json:"dest,omitempty"`
Username string `json:"username,omitempty"`
Username *string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Token string `json:"token,omitempty"`
Privileged bool `json:"privileged,omitempty"`
......@@ -555,7 +555,7 @@ func negotiate(c *webClient, down *rtpDownConnection, restartIce bool, replace s
Label: down.remote.Label(),
Replace: replace,
Source: source,
Username: username,
Username: &username,
SDP: down.pc.LocalDescription().SDP,
})
}
......@@ -930,7 +930,7 @@ type joinedAction struct {
type kickAction struct {
id string
username string
username *string
message string
}
......@@ -1160,11 +1160,12 @@ func handleAction(c *webClient, a interface{}) error {
return nil
}
perms := append([]string(nil), a.permissions...)
username := a.username
return c.write(clientMessage{
Type: "user",
Kind: a.kind,
Id: a.id,
Username: a.username,
Username: &username,
Permissions: perms,
Data: a.data,
})
......@@ -1181,11 +1182,12 @@ func handleAction(c *webClient, a interface{}) error {
}
}
perms := append([]string(nil), c.permissions...)
username := c.username
err := c.write(clientMessage{
Type: "joined",
Kind: a.kind,
Group: a.group,
Username: c.username,
Username: &username,
Permissions: perms,
Status: status,
Data: data,
......@@ -1222,11 +1224,12 @@ func handleAction(c *webClient, a interface{}) error {
}
perms := append([]string(nil), c.permissions...)
status := g.Status(true, "")
username := c.username
c.write(clientMessage{
Type: "joined",
Kind: "change",
Group: g.Name(),
Username: c.username,
Username: &username,
Permissions: perms,
Status: &status,
RTCConfiguration: ice.ICEConfiguration(),
......@@ -1360,7 +1363,7 @@ func setPermissions(g *group.Group, id string, perm string) error {
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})
}
......@@ -1368,7 +1371,7 @@ func (c *webClient) Joined(group, kind string) error {
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)
if client == nil {
return group.UserError("no such user")
......@@ -1385,8 +1388,8 @@ func handleClientMessage(c *webClient, m clientMessage) error {
}
if m.Type != "join" {
if m.Username != "" {
if m.Username != c.Username() {
if m.Username != nil {
if *m.Username != c.Username() {
return group.ProtocolError("spoofed username")
}
}
......@@ -1411,7 +1414,6 @@ func handleClientMessage(c *webClient, m clientMessage) error {
"cannot join multiple groups",
)
}
c.username = m.Username
c.data = m.Data
g, err := group.AddClient(m.Group, c,
group.ClientCredentials{
......@@ -1435,23 +1437,25 @@ func handleClientMessage(c *webClient, m clientMessage) error {
s = "internal server error"
log.Printf("Join group: %v", err)
}
username := c.username
return c.write(clientMessage{
Type: "joined",
Kind: "fail",
Error: e,
Group: m.Group,
Username: c.username,
Username: &username,
Value: s,
})
}
if redirect := g.Description().Redirect; redirect != "" {
// We normally redirect at the HTTP level, but the group
// description could have been edited in the meantime.
username := c.username
return c.write(clientMessage{
Type: "joined",
Kind: "redirect",
Group: m.Group,
Username: c.username,
Username: &username,
Value: redirect,
})
}
......@@ -1677,10 +1681,11 @@ func handleClientMessage(c *webClient, m clientMessage) error {
s = s + fmt.Sprintf("%v (%v client%v)\n",
sg.Name, sg.Clients, plural)
}
username := "Server"
c.write(clientMessage{
Type: "chat",
Dest: c.id,
Username: "Server",
Username: &username,
Time: time.Now().Format(time.RFC3339),
Value: s,
})
......
......@@ -642,7 +642,7 @@ func checkGroupPermissions(w http.ResponseWriter, r *http.Request, groupname str
_, p, err := g.GetPermission(
group.ClientCredentials{
Username: user,
Username: &user,
Password: pass,
},
)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment