mirror of
https://github.com/jech/galene.git
synced 2024-11-25 18:15:57 +01:00
Move password checking into group.go.
It used to be delegated to clients.
This commit is contained in:
parent
8135f6b91d
commit
869eb9b839
8 changed files with 60 additions and 97 deletions
|
@ -59,10 +59,6 @@ func (client *Client) Username() string {
|
||||||
return "RECORDING"
|
return "RECORDING"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) Challenge(group string, cred group.ClientCredentials) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *Client) SetPermissions(perms group.ClientPermissions) {
|
func (client *Client) SetPermissions(perms group.ClientPermissions) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ func main() {
|
||||||
}
|
}
|
||||||
e := json.NewEncoder(os.Stdout)
|
e := json.NewEncoder(os.Stdout)
|
||||||
if username != "" {
|
if username != "" {
|
||||||
creds := group.ClientCredentials{
|
creds := group.ClientPattern{
|
||||||
Username: username,
|
Username: username,
|
||||||
Password: &p,
|
Password: &p,
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ func (p Password) MarshalJSON() ([]byte, error) {
|
||||||
return json.Marshal(RawPassword(p))
|
return json.Marshal(RawPassword(p))
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientCredentials struct {
|
type ClientPattern struct {
|
||||||
Username string `json:"username,omitempty"`
|
Username string `json:"username,omitempty"`
|
||||||
Password *Password `json:"password,omitempty"`
|
Password *Password `json:"password,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -88,15 +88,16 @@ type ClientPermissions struct {
|
||||||
System bool `json:"system,omitempty"`
|
System bool `json:"system,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Challengeable interface {
|
type ClientCredentials struct {
|
||||||
Username() string
|
System bool
|
||||||
Challenge(string, ClientCredentials) bool
|
Username string
|
||||||
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
Group() *Group
|
Group() *Group
|
||||||
Id() string
|
Id() string
|
||||||
Challengeable
|
Username() string
|
||||||
Permissions() ClientPermissions
|
Permissions() ClientPermissions
|
||||||
SetPermissions(ClientPermissions)
|
SetPermissions(ClientPermissions)
|
||||||
Status() map[string]interface{}
|
Status() map[string]interface{}
|
||||||
|
|
|
@ -525,7 +525,7 @@ func deleteUnlocked(g *Group) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddClient(group string, c Client) (*Group, error) {
|
func AddClient(group string, c Client, creds ClientCredentials) (*Group, error) {
|
||||||
g, err := Add(group, nil)
|
g, err := Add(group, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -537,7 +537,7 @@ func AddClient(group string, c Client) (*Group, error) {
|
||||||
clients := g.getClientsUnlocked(nil)
|
clients := g.getClientsUnlocked(nil)
|
||||||
|
|
||||||
if !c.Permissions().System {
|
if !c.Permissions().System {
|
||||||
perms, err := g.description.GetPermission(group, c)
|
perms, err := g.description.GetPermission(group, creds)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -788,12 +788,16 @@ func (g *Group) GetChatHistory() []ChatHistoryEntry {
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchClient(group string, c Challengeable, users []ClientCredentials) (bool, bool) {
|
func matchClient(group string, creds ClientCredentials, users []ClientPattern) (bool, bool) {
|
||||||
matched := false
|
matched := false
|
||||||
for _, u := range users {
|
for _, u := range users {
|
||||||
if u.Username == c.Username() {
|
if u.Username == creds.Username {
|
||||||
matched = true
|
matched = true
|
||||||
if c.Challenge(group, u) {
|
if u.Password == nil {
|
||||||
|
return true, true
|
||||||
|
}
|
||||||
|
m, _ := u.Password.Match(creds.Password)
|
||||||
|
if m {
|
||||||
return true, true
|
return true, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,7 +808,11 @@ func matchClient(group string, c Challengeable, users []ClientCredentials) (bool
|
||||||
|
|
||||||
for _, u := range users {
|
for _, u := range users {
|
||||||
if u.Username == "" {
|
if u.Username == "" {
|
||||||
if c.Challenge(group, u) {
|
if u.Password == nil {
|
||||||
|
return true, true
|
||||||
|
}
|
||||||
|
m, _ := u.Password.Match(creds.Password)
|
||||||
|
if m {
|
||||||
return true, true
|
return true, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -865,13 +873,13 @@ type Description struct {
|
||||||
Autokick bool `json:"autokick,omitempty"`
|
Autokick bool `json:"autokick,omitempty"`
|
||||||
|
|
||||||
// A list of logins for ops.
|
// A list of logins for ops.
|
||||||
Op []ClientCredentials `json:"op,omitempty"`
|
Op []ClientPattern `json:"op,omitempty"`
|
||||||
|
|
||||||
// A list of logins for presenters.
|
// A list of logins for presenters.
|
||||||
Presenter []ClientCredentials `json:"presenter,omitempty"`
|
Presenter []ClientPattern `json:"presenter,omitempty"`
|
||||||
|
|
||||||
// A list of logins for non-presenting users.
|
// A list of logins for non-presenting users.
|
||||||
Other []ClientCredentials `json:"other,omitempty"`
|
Other []ClientPattern `json:"other,omitempty"`
|
||||||
|
|
||||||
// Codec preferences. If empty, a suitable default is chosen in
|
// Codec preferences. If empty, a suitable default is chosen in
|
||||||
// the APIFromNames function.
|
// the APIFromNames function.
|
||||||
|
@ -970,12 +978,12 @@ func GetDescription(name string) (*Description, error) {
|
||||||
return &desc, nil
|
return &desc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (desc *Description) GetPermission(group string, c Challengeable) (ClientPermissions, error) {
|
func (desc *Description) GetPermission(group string, creds ClientCredentials) (ClientPermissions, error) {
|
||||||
var p ClientPermissions
|
var p ClientPermissions
|
||||||
if !desc.AllowAnonymous && c.Username() == "" {
|
if !desc.AllowAnonymous && creds.Username == "" {
|
||||||
return p, ErrAnonymousNotAuthorised
|
return p, ErrAnonymousNotAuthorised
|
||||||
}
|
}
|
||||||
if found, good := matchClient(group, c, desc.Op); found {
|
if found, good := matchClient(group, creds, desc.Op); found {
|
||||||
if good {
|
if good {
|
||||||
p.Op = true
|
p.Op = true
|
||||||
p.Present = true
|
p.Present = true
|
||||||
|
@ -986,14 +994,14 @@ func (desc *Description) GetPermission(group string, c Challengeable) (ClientPer
|
||||||
}
|
}
|
||||||
return p, ErrNotAuthorised
|
return p, ErrNotAuthorised
|
||||||
}
|
}
|
||||||
if found, good := matchClient(group, c, desc.Presenter); found {
|
if found, good := matchClient(group, creds, desc.Presenter); found {
|
||||||
if good {
|
if good {
|
||||||
p.Present = true
|
p.Present = true
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
return p, ErrNotAuthorised
|
return p, ErrNotAuthorised
|
||||||
}
|
}
|
||||||
if found, good := matchClient(group, c, desc.Other); found {
|
if found, good := matchClient(group, creds, desc.Other); found {
|
||||||
if good {
|
if good {
|
||||||
return p, nil
|
return p, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,56 +136,36 @@ func TestDescriptionJSON(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type testClient struct {
|
var badClients = []ClientCredentials{
|
||||||
username string
|
{Username: "jch", Password: "foo"},
|
||||||
password string
|
{Username: "john", Password: "foo"},
|
||||||
|
{Username: "james", Password: "foo"},
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c testClient) Username() string {
|
type credPerm struct {
|
||||||
return c.username
|
c ClientCredentials
|
||||||
}
|
|
||||||
|
|
||||||
func (c testClient) Challenge(g string, creds ClientCredentials) bool {
|
|
||||||
if creds.Password == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
m, err := creds.Password.Match(c.password)
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
type testClientPerm struct {
|
|
||||||
c testClient
|
|
||||||
p ClientPermissions
|
p ClientPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
var badClients = []testClient{
|
var goodClients = []credPerm{
|
||||||
testClient{"jch", "foo"},
|
|
||||||
testClient{"john", "foo"},
|
|
||||||
testClient{"james", "foo"},
|
|
||||||
}
|
|
||||||
|
|
||||||
var goodClients = []testClientPerm{
|
|
||||||
{
|
{
|
||||||
testClient{"jch", "topsecret"},
|
ClientCredentials{Username: "jch", Password: "topsecret"},
|
||||||
ClientPermissions{Op: true, Present: true},
|
ClientPermissions{Op: true, Present: true},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testClient{"john", "secret"},
|
ClientCredentials{Username: "john", Password: "secret"},
|
||||||
ClientPermissions{Present: true},
|
ClientPermissions{Present: true},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testClient{"john", "secret2"},
|
ClientCredentials{Username: "john", Password: "secret2"},
|
||||||
ClientPermissions{Present: true},
|
ClientPermissions{Present: true},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testClient{"james", "secret3"},
|
ClientCredentials{Username: "james", Password: "secret3"},
|
||||||
ClientPermissions{},
|
ClientPermissions{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
testClient{"paul", "secret3"},
|
ClientCredentials{Username: "paul", Password: "secret3"},
|
||||||
ClientPermissions{},
|
ClientPermissions{},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -198,7 +178,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 := d.GetPermission("test", c)
|
p, err := d.GetPermission("test", 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)
|
||||||
|
@ -207,7 +187,7 @@ 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) {
|
||||||
p, err := d.GetPermission("test", cp.c)
|
p, err := d.GetPermission("test", cp.c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("GetPermission %v: %v", cp.c, err)
|
t.Errorf("GetPermission %v: %v", cp.c, err)
|
||||||
|
|
|
@ -37,4 +37,3 @@ func TestDownTrackAtomics(t *testing.T) {
|
||||||
t.Errorf("Expected %v, got %v", info, info2)
|
t.Errorf("Expected %v, got %v", info, info2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,6 @@ type webClient struct {
|
||||||
group *group.Group
|
group *group.Group
|
||||||
id string
|
id string
|
||||||
username string
|
username string
|
||||||
password string
|
|
||||||
permissions group.ClientPermissions
|
permissions group.ClientPermissions
|
||||||
status map[string]interface{}
|
status map[string]interface{}
|
||||||
requested map[string][]string
|
requested map[string][]string
|
||||||
|
@ -83,18 +82,6 @@ func (c *webClient) Username() string {
|
||||||
return c.username
|
return c.username
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *webClient) Challenge(group string, creds group.ClientCredentials) bool {
|
|
||||||
if creds.Password == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
m, err := creds.Password.Match(c.password)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Password match: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *webClient) Permissions() group.ClientPermissions {
|
func (c *webClient) Permissions() group.ClientPermissions {
|
||||||
return c.permissions
|
return c.permissions
|
||||||
}
|
}
|
||||||
|
@ -1343,8 +1330,12 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
return group.ProtocolError("cannot join multiple groups")
|
return group.ProtocolError("cannot join multiple groups")
|
||||||
}
|
}
|
||||||
c.username = m.Username
|
c.username = m.Username
|
||||||
c.password = m.Password
|
g, err := group.AddClient(m.Group, c,
|
||||||
g, err := group.AddClient(m.Group, c)
|
group.ClientCredentials{
|
||||||
|
Username: m.Username,
|
||||||
|
Password: m.Password,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var s string
|
var s string
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
|
@ -1583,7 +1574,11 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
disk := diskwriter.New(g)
|
disk := diskwriter.New(g)
|
||||||
_, err := group.AddClient(g.Name(), disk)
|
_, err := group.AddClient(g.Name(), disk,
|
||||||
|
group.ClientCredentials{
|
||||||
|
System: true,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
disk.Close()
|
disk.Close()
|
||||||
return c.error(err)
|
return c.error(err)
|
||||||
|
|
|
@ -534,27 +534,6 @@ func handleGroupAction(w http.ResponseWriter, r *http.Request, group string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpClient struct {
|
|
||||||
username string
|
|
||||||
password string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c httpClient) Username() string {
|
|
||||||
return c.username
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c httpClient) Challenge(group string, creds group.ClientCredentials) bool {
|
|
||||||
if creds.Password == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
m, err := creds.Password.Match(c.password)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Password match: %v", err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkGroupPermissions(w http.ResponseWriter, r *http.Request, groupname string) bool {
|
func checkGroupPermissions(w http.ResponseWriter, r *http.Request, groupname string) bool {
|
||||||
desc, err := group.GetDescription(groupname)
|
desc, err := group.GetDescription(groupname)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -566,7 +545,12 @@ func checkGroupPermissions(w http.ResponseWriter, r *http.Request, groupname str
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := desc.GetPermission(groupname, httpClient{user, pass})
|
p, err := desc.GetPermission(groupname,
|
||||||
|
group.ClientCredentials{
|
||||||
|
Username: user,
|
||||||
|
Password: pass,
|
||||||
|
},
|
||||||
|
)
|
||||||
if err != nil || !p.Record {
|
if err != nil || !p.Record {
|
||||||
if err == group.ErrNotAuthorised {
|
if err == group.ErrNotAuthorised {
|
||||||
time.Sleep(200 * time.Millisecond)
|
time.Sleep(200 * time.Millisecond)
|
||||||
|
|
Loading…
Reference in a new issue