Update a couple permissions things, no longer allow anonymous users.
This commit is contained in:
@@ -196,6 +196,9 @@ func (client *Client) PushConn(g *hall.Hall, id string, up conn.Up, tracks []con
|
||||
g.WallOps("Write to disk: " + err.Error())
|
||||
return err
|
||||
}
|
||||
if down == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
client.down[up.Id()] = down
|
||||
return nil
|
||||
@@ -699,7 +702,7 @@ func newDiskConn(client *Client, up conn.Up, remoteTracks []conn.UpTrack) (*disk
|
||||
}
|
||||
|
||||
if len(tracks) == 0 {
|
||||
return nil, errors.New("no usable tracks found")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
down := &diskConn{
|
||||
|
||||
@@ -8,6 +8,9 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.stormux.org/storm/skald/conn"
|
||||
"git.stormux.org/storm/skald/hall"
|
||||
)
|
||||
|
||||
func TestSanitise(t *testing.T) {
|
||||
@@ -195,6 +198,32 @@ func TestMixFrameReturnsNilForSilence(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewDiskConnIgnoresConnectionWithoutRecordableTracks(t *testing.T) {
|
||||
down, err := newDiskConn(&Client{}, &fakeUp{id: "up1"}, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if down != nil {
|
||||
t.Fatalf("expected no disk connection for no tracks, got %#v", down)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPushConnDoesNotStoreConnectionWithoutRecordableTracks(t *testing.T) {
|
||||
g := &hall.Hall{}
|
||||
client := &Client{
|
||||
hall: g,
|
||||
recorder: &recorder{},
|
||||
down: make(map[string]*diskConn),
|
||||
}
|
||||
err := client.PushConn(g, "up1", &fakeUp{id: "up1"}, nil, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(client.down) != 0 {
|
||||
t.Fatalf("stored %d down connections, expected 0", len(client.down))
|
||||
}
|
||||
}
|
||||
|
||||
func TestRecorderCreatesPlayableOgg(t *testing.T) {
|
||||
if _, err := exec.LookPath("ffmpeg"); err != nil {
|
||||
t.Skip("ffmpeg not installed")
|
||||
@@ -275,3 +304,13 @@ func pcmFrame(sample int16) []byte {
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
type fakeUp struct {
|
||||
id string
|
||||
}
|
||||
|
||||
func (u *fakeUp) AddLocal(conn.Down) error { return nil }
|
||||
func (u *fakeUp) DelLocal(conn.Down) bool { return true }
|
||||
func (u *fakeUp) Id() string { return u.id }
|
||||
func (u *fakeUp) Label() string { return "audio" }
|
||||
func (u *fakeUp) User() (string, string) { return "user-id", "Username" }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# shellcheck shell=bash disable=SC2034,SC2154
|
||||
|
||||
pkgname=skald-git
|
||||
pkgver=0.0.0.r1531.g08b484f
|
||||
pkgver=0.0.0.r1532.g3e06de7
|
||||
pkgrel=1
|
||||
pkgdesc='Audio-only hall-based conferencing server'
|
||||
arch=('x86_64' 'aarch64')
|
||||
|
||||
+7
-1
@@ -560,6 +560,12 @@ func AddClient(hall string, c Client, creds ClientCredentials) (*Hall, error) {
|
||||
c.SetUsername(username)
|
||||
c.SetPermissions(perms)
|
||||
|
||||
for _, cc := range clients {
|
||||
if !isSystemClient(cc) && cc.Username() == username {
|
||||
return nil, UserError("username already in use")
|
||||
}
|
||||
}
|
||||
|
||||
if !member("op", perms) {
|
||||
if g.locked != nil {
|
||||
m := *g.locked
|
||||
@@ -1005,7 +1011,7 @@ func (g *Hall) userExists(username string) bool {
|
||||
// usernames might lead to security vulnaribilities.
|
||||
// For now, we just do the minimal validation that avoids path traversal.
|
||||
func validUsername(username string) bool {
|
||||
return username == "" || validHallName(username)
|
||||
return username != "" && validHallName(username)
|
||||
}
|
||||
|
||||
// called locked
|
||||
|
||||
@@ -238,6 +238,83 @@ func strPtr(s string) *string {
|
||||
return &s
|
||||
}
|
||||
|
||||
func TestEmptyUsernameIsRejected(t *testing.T) {
|
||||
halls.halls = nil
|
||||
oldDirectory := Directory
|
||||
Directory = t.TempDir()
|
||||
t.Cleanup(func() {
|
||||
Directory = oldDirectory
|
||||
halls.halls = nil
|
||||
})
|
||||
|
||||
err := os.WriteFile(
|
||||
filepath.Join(Directory, "empty-username-test.json"),
|
||||
[]byte(`{
|
||||
"wildcard-user": {"password": "secret", "permissions": "present"}
|
||||
}`),
|
||||
0600,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = AddClient("empty-username-test", &testClient{id: "user1"}, ClientCredentials{
|
||||
Username: strPtr(""),
|
||||
Password: "secret",
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("empty username unexpectedly joined")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDuplicateUsernameIsRejected(t *testing.T) {
|
||||
halls.halls = nil
|
||||
oldDirectory := Directory
|
||||
Directory = t.TempDir()
|
||||
t.Cleanup(func() {
|
||||
Directory = oldDirectory
|
||||
halls.halls = nil
|
||||
})
|
||||
|
||||
err := os.WriteFile(
|
||||
filepath.Join(Directory, "duplicate-username-test.json"),
|
||||
[]byte(`{
|
||||
"wildcard-user": {"password": "secret", "permissions": "present"}
|
||||
}`),
|
||||
0600,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = AddClient("duplicate-username-test", &testClient{id: "user1"}, ClientCredentials{
|
||||
Username: strPtr("bob1"),
|
||||
Password: "secret",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = AddClient("duplicate-username-test", &testClient{id: "user2"}, ClientCredentials{
|
||||
Username: strPtr("bob1"),
|
||||
Password: "secret",
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatal("duplicate username unexpectedly joined")
|
||||
}
|
||||
if got, want := err.Error(), "username already in use"; got != want {
|
||||
t.Fatalf("duplicate username error = %q, want %q", got, want)
|
||||
}
|
||||
|
||||
_, err = AddClient("duplicate-username-test", &testClient{id: "user3"}, ClientCredentials{
|
||||
Username: strPtr("bob2"),
|
||||
Password: "secret",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("different username should join: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLockedHallJoinMessage(t *testing.T) {
|
||||
halls.halls = nil
|
||||
oldDirectory := Directory
|
||||
|
||||
@@ -376,7 +376,7 @@ are optional. The following fields are allowed:
|
||||
- `unrestricted-tokens`: if true, then ordinary users (without the "op"
|
||||
privilege) are allowed to create tokens;
|
||||
|
||||
- `allow-anonymous`: if true, then users may connect with an empty username;
|
||||
- `allow-anonymous`: obsolete and ignored. Empty usernames are rejected;
|
||||
|
||||
- `auto-subhalls`: if true, then subhalls of the form `hall/subhall`
|
||||
are automatically created when first accessed;
|
||||
@@ -410,6 +410,11 @@ following strings:
|
||||
- `caption`: a user with the right to display captions (only);
|
||||
- `admin`: a user with the right to administer the hall (only).
|
||||
|
||||
Usernames must be non-empty and unique among connected non-system clients in a
|
||||
hall. If a `wildcard-user` is configured, users may choose arbitrary names
|
||||
that are not listed in `users`, but two connected users may not use the same
|
||||
name.
|
||||
|
||||
The value of the `codecs` field is an array of codecs allowed in the
|
||||
hall. Supported audio codecs include `"opus"`, `"g722"`, `"pcmu"` and
|
||||
`"pcma"`. Opus is the default and is the codec used by Skald's
|
||||
|
||||
Reference in New Issue
Block a user