mirror of
https://github.com/mumble-voip/grumble.git
synced 2025-12-19 21:59:59 -08:00
Add SetSuperUserPassword ctl option.
This commit is contained in:
parent
b4a9f706ec
commit
5b1cfd14f1
5 changed files with 66 additions and 22 deletions
20
ctl.go
20
ctl.go
|
|
@ -21,6 +21,9 @@ var CtlUsage = `grumble ctl
|
||||||
stop [id]
|
stop [id]
|
||||||
Stop a server
|
Stop a server
|
||||||
|
|
||||||
|
supw [id] [password]
|
||||||
|
Set the SuperUser password for server with id
|
||||||
|
|
||||||
setconf [id] [key] [value]
|
setconf [id] [key] [value]
|
||||||
Set a config value for server with id
|
Set a config value for server with id
|
||||||
|
|
||||||
|
|
@ -56,12 +59,21 @@ func GrumbleCtl(args []string) {
|
||||||
log.Fatalf("Unable to stop: %v", err)
|
log.Fatalf("Unable to stop: %v", err)
|
||||||
}
|
}
|
||||||
log.Printf("[%v] Stopped", sid)
|
log.Printf("[%v] Stopped", sid)
|
||||||
|
case "supw":
|
||||||
|
if len(args) < 3 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := client.Call("ctl.SetSuperUserPassword", &KeyValuePair{sid, "", args[2]}, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Unable to set SuperUser password: %v", err)
|
||||||
|
}
|
||||||
|
log.Printf("[%v] Set SuperUser password", sid)
|
||||||
case "setconf":
|
case "setconf":
|
||||||
if len(args) < 4 {
|
if len(args) < 4 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result := &ConfigValue{}
|
result := &KeyValuePair{}
|
||||||
err := client.Call("ctl.SetConfig", &ConfigValue{sid, args[2], args[3]}, result)
|
err := client.Call("ctl.SetConfig", &KeyValuePair{sid, args[2], args[3]}, result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to set config: %v", err)
|
log.Fatalf("Unable to set config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -70,8 +82,8 @@ func GrumbleCtl(args []string) {
|
||||||
if len(args) < 3 {
|
if len(args) < 3 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
result := &ConfigValue{}
|
result := &KeyValuePair{}
|
||||||
err := client.Call("ctl.GetConfig", &ConfigValue{sid, args[2], ""}, result)
|
err := client.Call("ctl.GetConfig", &KeyValuePair{sid, args[2], ""}, result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Unable to get config: %v", err)
|
log.Fatalf("Unable to get config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
ctlrpc.go
24
ctlrpc.go
|
|
@ -9,11 +9,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ControlRPC struct {
|
type ControlRPC struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
type KeyValuePair struct {
|
||||||
|
Id int64
|
||||||
|
Key string
|
||||||
|
Value string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a server
|
// Start a server
|
||||||
func (c *ControlRPC) Start(Id int64, out *int) os.Error {
|
func (c *ControlRPC) Start(Id int64, out *int64) os.Error {
|
||||||
server, exists := servers[Id]
|
server, exists := servers[Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return os.NewError("no such server")
|
||||||
|
|
@ -32,14 +37,19 @@ func (c *ControlRPC) Stop(Id int64, out *int) os.Error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ConfigValue struct {
|
// Set SuperUser password
|
||||||
Id int64
|
func (c *ControlRPC) SetSuperUserPassword(in *KeyValuePair, out *int64) os.Error {
|
||||||
Key string
|
server, exists := servers[in.Id]
|
||||||
Value string
|
if !exists {
|
||||||
|
return os.NewError("no such server")
|
||||||
|
}
|
||||||
|
server.SetSuperUserPassword(in.Value)
|
||||||
|
*out = in.Id
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set a config value
|
// Set a config value
|
||||||
func (c *ControlRPC) SetConfig(in *ConfigValue, out *ConfigValue) os.Error {
|
func (c *ControlRPC) SetConfig(in *KeyValuePair, out *KeyValuePair) os.Error {
|
||||||
server, exists := servers[in.Id]
|
server, exists := servers[in.Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return os.NewError("no such server")
|
||||||
|
|
@ -52,7 +62,7 @@ func (c *ControlRPC) SetConfig(in *ConfigValue, out *ConfigValue) os.Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a config value
|
// Get a config value
|
||||||
func (c *ControlRPC) GetConfig(in *ConfigValue, out *ConfigValue) os.Error {
|
func (c *ControlRPC) GetConfig(in *KeyValuePair, out *KeyValuePair) os.Error {
|
||||||
server, exists := servers[in.Id]
|
server, exists := servers[in.Id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return os.NewError("no such server")
|
return os.NewError("no such server")
|
||||||
|
|
|
||||||
|
|
@ -199,7 +199,6 @@ func (channel *Channel) Freeze() (fc frozenChannel, err os.Error) {
|
||||||
func (user *User) Freeze() (fu frozenUser, err os.Error) {
|
func (user *User) Freeze() (fu frozenUser, err os.Error) {
|
||||||
fu.Id = user.Id
|
fu.Id = user.Id
|
||||||
fu.Name = user.Name
|
fu.Name = user.Name
|
||||||
fu.Password = user.Password
|
|
||||||
fu.CertHash = user.CertHash
|
fu.CertHash = user.CertHash
|
||||||
fu.Email = user.Email
|
fu.Email = user.Email
|
||||||
fu.TextureBlob = user.TextureBlob
|
fu.TextureBlob = user.TextureBlob
|
||||||
|
|
@ -320,7 +319,6 @@ func NewServerFromFrozen(filename string) (s *Server, err os.Error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Password = fu.Password
|
|
||||||
u.CertHash = fu.CertHash
|
u.CertHash = fu.CertHash
|
||||||
u.Email = fu.Email
|
u.Email = fu.Email
|
||||||
u.TextureBlob = fu.TextureBlob
|
u.TextureBlob = fu.TextureBlob
|
||||||
|
|
|
||||||
|
|
@ -355,13 +355,15 @@ func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if UserId == 0 {
|
||||||
|
server.SuperUserPassword = "sha1$$" + SHA1Password
|
||||||
|
}
|
||||||
|
|
||||||
user, err := NewUser(uint32(UserId), UserName)
|
user, err := NewUser(uint32(UserId), UserName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
user.Password = "sha1$$" + SHA1Password
|
|
||||||
|
|
||||||
key, err := blobstore.Put(Texture)
|
key, err := blobstore.Put(Texture)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
||||||
36
server.go
36
server.go
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
|
"crypto/rand"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -86,6 +87,9 @@ type Server struct {
|
||||||
root *Channel
|
root *Channel
|
||||||
Channels map[int]*Channel
|
Channels map[int]*Channel
|
||||||
|
|
||||||
|
// Administration
|
||||||
|
SuperUserPassword string
|
||||||
|
|
||||||
// Users
|
// Users
|
||||||
Users map[uint32]*User
|
Users map[uint32]*User
|
||||||
UserCertMap map[string]*User
|
UserCertMap map[string]*User
|
||||||
|
|
@ -150,6 +154,7 @@ func NewServer(id int64, addr string, port int) (s *Server, err os.Error) {
|
||||||
s.freezeRequest = make(chan *freezeRequest)
|
s.freezeRequest = make(chan *freezeRequest)
|
||||||
s.clientAuthenticated = make(chan *Client)
|
s.clientAuthenticated = make(chan *Client)
|
||||||
|
|
||||||
|
s.Users[0], err = NewUser(0, "SuperUser")
|
||||||
s.Channels = make(map[int]*Channel)
|
s.Channels = make(map[int]*Channel)
|
||||||
s.root = s.NewChannel(0, "Root")
|
s.root = s.NewChannel(0, "Root")
|
||||||
s.aclcache = NewACLCache()
|
s.aclcache = NewACLCache()
|
||||||
|
|
@ -159,14 +164,27 @@ func NewServer(id int64, addr string, port int) (s *Server, err os.Error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether password matches the set SuperUser password.
|
// Set password as the new SuperUser password
|
||||||
func (server *Server) CheckSuperUserPassword(password string) bool {
|
func (server *Server) SetSuperUserPassword(password string) {
|
||||||
superUser, exists := server.Users[0]
|
saltBytes := make([]byte, 24)
|
||||||
if !exists {
|
_, err := rand.Read(saltBytes)
|
||||||
server.Panicf("Fatal error: No SuperUser for server %v", server.Id)
|
if err != nil {
|
||||||
|
server.Fatalf("Unable to read from crypto/rand: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
parts := strings.Split(superUser.Password, "$", -1)
|
salt := hex.EncodeToString(saltBytes)
|
||||||
|
hasher := sha1.New()
|
||||||
|
hasher.Write(saltBytes)
|
||||||
|
hasher.Write([]byte(password))
|
||||||
|
digest := hex.EncodeToString(hasher.Sum())
|
||||||
|
|
||||||
|
// Could be racy, but shouldn't really matter...
|
||||||
|
server.SuperUserPassword = "sha1$" + salt + "$" + digest
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether password matches the set SuperUser password.
|
||||||
|
func (server *Server) CheckSuperUserPassword(password string) bool {
|
||||||
|
parts := strings.Split(server.SuperUserPassword, "$", -1)
|
||||||
if len(parts) != 3 {
|
if len(parts) != 3 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -186,7 +204,11 @@ func (server *Server) CheckSuperUserPassword(password string) bool {
|
||||||
|
|
||||||
// salt
|
// salt
|
||||||
if len(parts[1]) > 0 {
|
if len(parts[1]) > 0 {
|
||||||
h.Write([]byte(parts[1]))
|
saltBytes, err := hex.DecodeString(parts[1])
|
||||||
|
if err != nil {
|
||||||
|
server.Fatalf("Unable to decode salt: %v", err)
|
||||||
|
}
|
||||||
|
h.Write(saltBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
// password
|
// password
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue