1
0
Fork 0
forked from External/grumble

Add SetSuperUserPassword ctl option.

This commit is contained in:
Mikkel Krautz 2011-05-19 23:37:02 +02:00
parent b4a9f706ec
commit 5b1cfd14f1
5 changed files with 66 additions and 22 deletions

20
ctl.go
View file

@ -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)
} }

View file

@ -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")

View file

@ -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

View file

@ -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

View file

@ -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