1
0
Fork 0
forked from External/grumble

Recognize registered users by their certificate hash.

This commit is contained in:
Mikkel Krautz 2011-04-09 21:34:02 +02:00
parent 9036cd64af
commit 58fca6bcf7
9 changed files with 215 additions and 164 deletions

4
acl.go
View file

@ -143,7 +143,7 @@ func NewChannelACL(channel *Channel) *ChannelACL {
// and not a combination of permissions.
func (server *Server) HasPermission(client *Client, channel *Channel, perm Permission) bool {
// SuperUser can't speak or whisper, but everything else is OK
if client.UserId == 0 {
if client.IsSuperUser() {
if perm == SpeakPermission || perm == WhisperPermission {
return false
}
@ -193,7 +193,7 @@ func (server *Server) HasPermission(client *Client, channel *Channel, perm Permi
//
// If it's a group ACL, we have to parse and interpret the group string in the
// current context to determine membership. For that we use GroupMemberCheck.
matchUser := acl.IsUserACL() && acl.UserId == client.UserId
matchUser := acl.IsUserACL() && acl.UserId == client.UserId()
matchGroup := GroupMemberCheck(channel, iter, acl.Group, client)
if matchUser || matchGroup {
if acl.Allow.IsSet(TraversePermission) {

View file

@ -37,6 +37,15 @@ type Client struct {
codecs []int32
udp bool
// If the client is a registered user on the server,
// the user field will point to the registration record.
user *User
// If the client has SuperUser privileges, superUser will be true.
// Note that Grumble doesn't store credentials of the SuperUser in
// the user data store, so we have to keep track of it separately.
superUser bool
// Version
Version uint32
ClientName string
@ -50,10 +59,9 @@ type Client struct {
TextureHash []byte
// Personal
UserId int
Session uint32
Username string
Hash string
Session uint32
CertHash string
Tokens []string
Channel *Channel
SelfMute bool
@ -67,6 +75,40 @@ type Client struct {
PluginIdentity string
}
// Is the client a registered user?
func (client *Client) IsRegistered() bool {
return client.user != nil || client.IsSuperUser()
}
// Does the client have a certificate?
func (client *Client) HasCertificate() bool {
return len(client.CertHash) > 0
}
// Is the client the SuperUser?
func (client *Client) IsSuperUser() bool {
return client.superUser
}
// Get the User ID of this client.
// Returns -1 if the client is not a registered user.
func (client *Client) UserId() int {
if client.user == nil {
return -1
} else if client.superUser {
return 0
}
return int(client.user.Id)
}
// Get the client's shown name.
func (client *Client) ShownName() string {
if client.IsRegistered() {
return client.user.Name
}
return client.Username
}
// Something invalid happened on the wire.
func (client *Client) Panic(reason string) {
log.Printf("Client panic: %s", reason)
@ -103,8 +145,8 @@ func (client *Client) RejectAuth(kind, reason string) {
}
client.sendProtoMessage(MessageReject, &mumbleproto.Reject{
Type: mumbleproto.NewReject_RejectType(mumbleproto.Reject_RejectType_value[kind]),
Reason: reasonString,
Type: mumbleproto.NewReject_RejectType(mumbleproto.Reject_RejectType_value[kind]),
Reason: reasonString,
})
client.ForceDisconnect()

View file

@ -182,7 +182,7 @@ func NewServerFromFrozen(filename string) (s *Server, err os.Error) {
decoder := gob.NewDecoder(zr)
decoder.Decode(&fs)
s, err = NewServer(int64(fs.Id), "", int(DefaultPort+fs.Id-1))
s, err = NewServer(int64(fs.Id), "0.0.0.0", int(DefaultPort+fs.Id-1))
if err != nil {
return nil, err
}

View file

@ -198,7 +198,7 @@ func GroupMemberCheck(current *Channel, aclchan *Channel, name string, client *C
// The user is part of the auth group is he is authenticated. That is,
// his UserId is >= 0.
} else if name == "auth" {
member = client.UserId >= 0
member = client.IsRegistered()
// The user is part of the strong group if he is authenticated to the server
// via a strong certificate (i.e. non-self-signed).
} else if name == "strong" {
@ -329,10 +329,10 @@ func GroupMemberCheck(current *Channel, aclchan *Channel, name string, client *C
}
for _, group := range groups {
if group.AddContains(client.UserId) || group.TemporaryContains(client.UserId) || group.TemporaryContains(-int(client.Session)) {
if group.AddContains(client.UserId()) || group.TemporaryContains(client.UserId()) || group.TemporaryContains(-int(client.Session)) {
member = true
}
if group.RemoveContains(client.UserId) {
if group.RemoveContains(client.UserId()) {
member = false
}
}

View file

@ -100,7 +100,6 @@ func main() {
}
log.Printf("Using blob directory: %s", *blobdir)
// Should we import data from a Murmur SQLite file?
if len(*sqlitedb) > 0 {
f, err := os.Open(*datadir)
@ -139,7 +138,7 @@ func main() {
f, err := os.Open(*datadir)
if err != nil {
log.Fatalf("Murmur import failed: %s", err.String())
log.Fatalf("Murmur import failed: %s", err.String())
}
defer f.Close()

View file

@ -223,7 +223,7 @@ func (server *Server) handleChannelStateMessage(client *Client, msg *Message) {
}
// Only registered users can create channels.
if client.UserId < 0 && len(client.Hash) == 0 {
if !client.IsRegistered() && !client.HasCertificate() {
client.sendPermissionDeniedTypeUser("MissingCertificate", client)
return
}
@ -251,9 +251,9 @@ func (server *Server) handleChannelStateMessage(client *Client, msg *Message) {
}
// Add the creator to the channel's admin group
if client.UserId >= 0 {
if client.IsRegistered() {
grp := NewGroup(channel, "admin")
grp.Add[client.UserId] = true
grp.Add[client.UserId()] = true
channel.Groups["admin"] = grp
}
@ -263,10 +263,10 @@ func (server *Server) handleChannelStateMessage(client *Client, msg *Message) {
acl := NewChannelACL(channel)
acl.ApplyHere = true
acl.ApplySubs = true
if client.UserId >= 0 {
acl.UserId = client.UserId
if client.IsRegistered() {
acl.UserId = client.UserId()
} else {
acl.Group = "$" + client.Hash
acl.Group = "$" + client.CertHash
}
acl.Deny = Permission(NonePermission)
acl.Allow = Permission(WritePermission | TraversePermission)
@ -464,8 +464,8 @@ func (server *Server) handleUserRemoveMessage(client *Client, msg *Message) {
client.Panic(err.String())
}
// Get the user to be removed.
user, ok := server.clients[*userremove.Session]
// Get the client to be removed.
removeClient, ok := server.clients[*userremove.Session]
if !ok {
client.Panic("Invalid session in UserRemove message")
return
@ -476,12 +476,13 @@ func (server *Server) handleUserRemoveMessage(client *Client, msg *Message) {
ban = *userremove.Ban
}
// Check user's permissions
// Check client's permissions
perm := Permission(KickPermission)
if ban {
perm = Permission(BanPermission)
}
if user.UserId == 0 || !server.HasPermission(client, server.root, perm) {
if removeClient.IsSuperUser() || !server.HasPermission(client, server.root, perm) {
client.sendPermissionDenied(client, server.root, perm)
return
}
@ -497,7 +498,7 @@ func (server *Server) handleUserRemoveMessage(client *Client, msg *Message) {
return
}
user.ForceDisconnect()
removeClient.ForceDisconnect()
}
// Handle user state changes
@ -513,16 +514,16 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
log.Panic("Client not found in server's client map.")
return
}
user := actor
target := actor
if userstate.Session != nil {
user, ok = server.clients[*userstate.Session]
target, ok = server.clients[*userstate.Session]
if !ok {
client.Panic("Invalid session in UserState message")
return
}
}
userstate.Session = proto.Uint32(user.Session)
userstate.Session = proto.Uint32(target.Session)
userstate.Actor = proto.Uint32(actor.Session)
// Does it have a channel ID?
@ -535,15 +536,15 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
// If the user and the actor aren't the same, check whether the actor has MovePermission on
// the user's curent channel.
if actor != user && !server.HasPermission(actor, user.Channel, MovePermission) {
client.sendPermissionDenied(actor, user.Channel, MovePermission)
if actor != target && !server.HasPermission(actor, target.Channel, MovePermission) {
client.sendPermissionDenied(actor, target.Channel, MovePermission)
return
}
// Check whether the actor has MovePermission on dstChan. Check whether user has EnterPermission
// on dstChan.
if !server.HasPermission(actor, dstChan, MovePermission) && !server.HasPermission(user, dstChan, EnterPermission) {
client.sendPermissionDenied(user, dstChan, EnterPermission)
if !server.HasPermission(actor, dstChan, MovePermission) && !server.HasPermission(target, dstChan, EnterPermission) {
client.sendPermissionDenied(target, dstChan, EnterPermission)
return
}
@ -552,20 +553,20 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
if userstate.Mute != nil || userstate.Deaf != nil || userstate.Suppress != nil || userstate.PrioritySpeaker != nil {
// Disallow for SuperUser
if user.UserId == 0 {
if target.IsSuperUser() {
client.sendPermissionDeniedType("SuperUser")
return
}
// Check whether the actor has 'mutedeafen' permission on user's channel.
if !server.HasPermission(actor, user.Channel, MuteDeafenPermission) {
client.sendPermissionDenied(actor, user.Channel, MuteDeafenPermission)
if !server.HasPermission(actor, target.Channel, MuteDeafenPermission) {
client.sendPermissionDenied(actor, target.Channel, MuteDeafenPermission)
return
}
// Check if this was a suppress operation. Only the server can suppress users.
if userstate.Suppress != nil {
client.sendPermissionDenied(actor, user.Channel, MuteDeafenPermission)
client.sendPermissionDenied(actor, target.Channel, MuteDeafenPermission)
return
}
}
@ -575,7 +576,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
comment := *userstate.Comment
// Clearing another user's comment.
if user != actor {
if target != actor {
// Check if actor has 'move' permissions on the root channel. It is needed
// to clear another user's comment.
if !server.HasPermission(actor, server.root, MovePermission) {
@ -594,7 +595,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
// Only set the comment if it is different from the current
// user comment.
if comment == user.Comment {
if comment == target.Comment {
userstate.Comment = nil
}
}
@ -610,7 +611,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
// If user != actor, check for RegisterPermission permission on root channel.
permCheck := Permission(NonePermission)
uid := *userstate.UserId
if user == actor {
if target == actor {
permCheck = SelfRegisterPermission
} else {
permCheck = RegisterPermission
@ -621,8 +622,8 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
}
// We can't register a user with an empty hash.
if len(user.Hash) == 0 {
client.sendPermissionDeniedTypeUser("MissingCertificate", user)
if len(target.CertHash) == 0 {
client.sendPermissionDeniedTypeUser("MissingCertificate", target)
}
}
@ -635,7 +636,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
// - PluginContext
// - PluginIdentity
// - Recording
if actor != user && (userstate.SelfDeaf != nil || userstate.SelfMute != nil ||
if actor != target && (userstate.SelfDeaf != nil || userstate.SelfMute != nil ||
userstate.Texture != nil || userstate.PluginContext != nil || userstate.PluginIdentity != nil ||
userstate.Recording != nil) {
client.Panic("Invalid UserState")
@ -645,86 +646,86 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
broadcast := false
if userstate.Texture != nil {
user.Texture = userstate.Texture
if len(user.Texture) >= 128 {
target.Texture = userstate.Texture
if len(target.Texture) >= 128 {
hash := sha1.New()
hash.Write(user.Texture)
user.TextureHash = hash.Sum()
hash.Write(target.Texture)
target.TextureHash = hash.Sum()
} else {
user.TextureHash = []byte{}
target.TextureHash = []byte{}
}
broadcast = true
}
if userstate.SelfDeaf != nil {
user.SelfDeaf = *userstate.SelfDeaf
if user.SelfDeaf {
target.SelfDeaf = *userstate.SelfDeaf
if target.SelfDeaf {
userstate.SelfDeaf = proto.Bool(true)
user.SelfMute = true
target.SelfMute = true
}
broadcast = true
}
if userstate.SelfMute != nil {
user.SelfMute = *userstate.SelfMute
if !user.SelfMute {
target.SelfMute = *userstate.SelfMute
if !target.SelfMute {
userstate.SelfDeaf = proto.Bool(false)
user.SelfDeaf = false
target.SelfDeaf = false
}
}
if userstate.PluginContext != nil {
user.PluginContext = userstate.PluginContext
target.PluginContext = userstate.PluginContext
}
if userstate.PluginIdentity != nil {
user.PluginIdentity = *userstate.PluginIdentity
target.PluginIdentity = *userstate.PluginIdentity
}
if userstate.Comment != nil {
user.Comment = *userstate.Comment
if len(user.Comment) >= 128 {
target.Comment = *userstate.Comment
if len(target.Comment) >= 128 {
hash := sha1.New()
hash.Write([]byte(user.Comment))
user.CommentHash = hash.Sum()
hash.Write([]byte(target.Comment))
target.CommentHash = hash.Sum()
} else {
user.CommentHash = []byte{}
target.CommentHash = []byte{}
}
broadcast = true
}
if userstate.Mute != nil || userstate.Deaf != nil || userstate.Suppress != nil || userstate.PrioritySpeaker != nil {
if userstate.Deaf != nil {
user.Deaf = *userstate.Deaf
if user.Deaf {
target.Deaf = *userstate.Deaf
if target.Deaf {
userstate.Mute = proto.Bool(true)
}
}
if userstate.Mute != nil {
user.Mute = *userstate.Mute
if !user.Mute {
target.Mute = *userstate.Mute
if !target.Mute {
userstate.Deaf = proto.Bool(false)
user.Deaf = false
target.Deaf = false
}
}
if userstate.Suppress != nil {
user.Suppress = *userstate.Suppress
target.Suppress = *userstate.Suppress
}
if userstate.PrioritySpeaker != nil {
user.PrioritySpeaker = *userstate.PrioritySpeaker
target.PrioritySpeaker = *userstate.PrioritySpeaker
}
broadcast = true
}
if userstate.Recording != nil && *userstate.Recording != user.Recording {
user.Recording = *userstate.Recording
if userstate.Recording != nil && *userstate.Recording != target.Recording {
target.Recording = *userstate.Recording
txtmsg := &mumbleproto.TextMessage{}
txtmsg.TreeId = append(txtmsg.TreeId, uint32(0))
if user.Recording {
txtmsg.Message = proto.String(fmt.Sprintf("User '%s' started recording", user.Username))
if target.Recording {
txtmsg.Message = proto.String(fmt.Sprintf("User '%s' started recording", target.Username))
} else {
txtmsg.Message = proto.String(fmt.Sprintf("User '%s' stopped recording", user.Username))
txtmsg.Message = proto.String(fmt.Sprintf("User '%s' stopped recording", target.Username))
}
server.broadcastProtoMessageWithPredicate(MessageTextMessage, txtmsg, func(client *Client) bool {
@ -743,7 +744,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
if userstate.ChannelId != nil {
channel, ok := server.Channels[int(*userstate.ChannelId)]
if ok {
server.userEnterChannel(user, channel, userstate)
server.userEnterChannel(target, channel, userstate)
broadcast = true
}
}
@ -754,10 +755,10 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
// textures that were sent over the wire. We can use this to determine
// whether a texture is a "new style" or an "old style" texture.
texlen := uint32(0)
if user.Texture != nil && len(user.Texture) > 4 {
texlen = uint32(user.Texture[0])<<24 | uint32(user.Texture[1])<<16 | uint32(user.Texture[2])<<8 | uint32(user.Texture[3])
if target.Texture != nil && len(target.Texture) > 4 {
texlen = uint32(target.Texture[0])<<24 | uint32(target.Texture[1])<<16 | uint32(target.Texture[2])<<8 | uint32(target.Texture[3])
}
if userstate.Texture != nil && len(user.Texture) > 4 && texlen != 600*60*4 {
if userstate.Texture != nil && len(target.Texture) > 4 && texlen != 600*60*4 {
// The sent texture is a new-style texture. Strip it from the message
// we send to pre-1.2.2 clients.
userstate.Texture = nil
@ -768,7 +769,7 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
log.Panic("Unable to broadcast UserState")
}
// Re-add it to the message, so that 1.2.2+ clients *do* get the new-style texture.
userstate.Texture = user.Texture
userstate.Texture = target.Texture
} else {
// Old style texture. We can send the message as-is.
err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool {
@ -782,14 +783,14 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
// If a texture hash is set on user, we transmit that instead of
// the texture itself. This allows the client to intelligently fetch
// the blobs that it does not already have in its local storage.
if userstate != nil && len(user.TextureHash) > 0 {
if userstate != nil && len(target.TextureHash) > 0 {
userstate.Texture = nil
userstate.TextureHash = user.TextureHash
userstate.TextureHash = target.TextureHash
}
// Ditto for comments.
if userstate.Comment != nil && len(user.CommentHash) > 0 {
if userstate.Comment != nil && len(target.CommentHash) > 0 {
userstate.Comment = nil
userstate.CommentHash = user.CommentHash
userstate.CommentHash = target.CommentHash
}
err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool {
@ -816,7 +817,7 @@ func (server *Server) handleTextMessage(client *Client, msg *Message) {
// fixme(mkrautz): Check text message length.
// fixme(mkrautz): Sanitize text as well.
users := make(map[uint32]*Client)
clients := make(map[uint32]*Client)
// Tree
for _, chanid := range txtmsg.TreeId {
@ -824,8 +825,8 @@ func (server *Server) handleTextMessage(client *Client, msg *Message) {
if !server.HasPermission(client, channel, TextMessagePermission) {
client.sendPermissionDenied(client, channel, TextMessagePermission)
}
for _, user := range channel.clients {
users[user.Session] = user
for _, target := range channel.clients {
clients[target.Session] = target
}
}
}
@ -837,28 +838,28 @@ func (server *Server) handleTextMessage(client *Client, msg *Message) {
client.sendPermissionDenied(client, channel, TextMessagePermission)
return
}
for _, user := range channel.clients {
users[user.Session] = user
for _, target := range channel.clients {
clients[target.Session] = target
}
}
}
// Direct-to-users
// Direct-to-clients
for _, session := range txtmsg.Session {
if user, ok := server.clients[session]; ok {
if !server.HasPermission(client, user.Channel, TextMessagePermission) {
client.sendPermissionDenied(client, user.Channel, TextMessagePermission)
if target, ok := server.clients[session]; ok {
if !server.HasPermission(client, target.Channel, TextMessagePermission) {
client.sendPermissionDenied(client, target.Channel, TextMessagePermission)
return
}
users[session] = user
clients[session] = target
}
}
// Remove ourselves
users[client.Session] = nil, false
clients[client.Session] = nil, false
for _, user := range users {
user.sendProtoMessage(MessageTextMessage, &mumbleproto.TextMessage{
for _, target := range clients {
target.sendProtoMessage(MessageTextMessage, &mumbleproto.TextMessage{
Actor: proto.Uint32(client.Session),
Message: txtmsg.Message,
})
@ -1052,17 +1053,16 @@ func (server *Server) handleAclMessage(client *Client, msg *Message) {
server.ClearACLCache()
// Regular user?
if !server.HasPermission(client, channel, WritePermission) && (client.UserId >= 0 || len(client.Hash) > 0) {
if !server.HasPermission(client, channel, WritePermission) && client.IsRegistered() || client.HasCertificate() {
chanacl := NewChannelACL(channel)
chanacl.ApplyHere = true
chanacl.ApplySubs = false
if client.UserId >= 0 {
chanacl.UserId = client.UserId
} else {
chanacl.Group = "$" + client.Hash
if client.IsRegistered() {
chanacl.UserId = client.UserId()
} else if client.HasCertificate() {
chanacl.Group = "$" + client.CertHash
}
chanacl.UserId = client.UserId
chanacl.Deny = Permission(NonePermission)
chanacl.Allow = Permission(WritePermission | TraversePermission)
@ -1121,11 +1121,11 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
// Request for user textures
if len(blobreq.SessionTexture) > 0 {
for _, sid := range blobreq.SessionTexture {
if user, ok := server.clients[sid]; ok {
if len(user.Texture) > 0 {
if target, ok := server.clients[sid]; ok {
if len(target.Texture) > 0 {
userstate.Reset()
userstate.Session = proto.Uint32(uint32(user.Session))
userstate.Texture = user.Texture
userstate.Session = proto.Uint32(uint32(target.Session))
userstate.Texture = target.Texture
if err := client.sendProtoMessage(MessageUserState, userstate); err != nil {
client.Panic(err.String())
return
@ -1138,11 +1138,11 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
// Request for user comments
if len(blobreq.SessionComment) > 0 {
for _, sid := range blobreq.SessionComment {
if user, ok := server.clients[sid]; ok {
if len(user.Comment) > 0 {
if target, ok := server.clients[sid]; ok {
if len(target.Comment) > 0 {
userstate.Reset()
userstate.Session = proto.Uint32(uint32(user.Session))
userstate.Comment = proto.String(user.Comment)
userstate.Session = proto.Uint32(uint32(target.Session))
userstate.Comment = proto.String(target.Comment)
if err := client.sendProtoMessage(MessageUserState, userstate); err != nil {
client.Panic(err.String())
return

View file

@ -31,7 +31,7 @@ const (
// Create a new Server from a Murmur SQLite database
func NewServerFromSQLite(id int64, db *sqlite.Conn) (s *Server, err os.Error) {
s, err = NewServer(id, "", int(DefaultPort + id - 1))
s, err = NewServer(id, "", int(DefaultPort+id-1))
if err != nil {
return nil, err
}
@ -73,8 +73,8 @@ func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int)
for stmt.Next() {
var (
name string
chanid int
name string
chanid int
inherit bool
)
err = stmt.Scan(&chanid, &name, &inherit)
@ -139,12 +139,12 @@ func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int)
for stmt.Next() {
var (
UserId string
Group string
UserId string
Group string
ApplyHere bool
ApplySub bool
Allow int64
Deny int64
ApplySub bool
Allow int64
Deny int64
)
if err := stmt.Scan(&UserId, &Group, &ApplyHere, &ApplySub, &Allow, &Deny); err != nil {
return err
@ -184,9 +184,9 @@ func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int)
for stmt.Next() {
var (
GroupId int64
Name string
Inherit bool
GroupId int64
Name string
Inherit bool
Inheritable bool
)
@ -216,7 +216,7 @@ func populateChannelsFromDatabase(server *Server, db *sqlite.Conn, parentId int)
for stmt.Next() {
var (
UserId int64
Add bool
Add bool
)
if err := stmt.Scan(&UserId, &Add); err != nil {
@ -256,7 +256,7 @@ func populateChannelLinkInfo(server *Server, db *sqlite.Conn) (err os.Error) {
for stmt.Next() {
var (
ChannelId int
LinkId int
LinkId int
)
if err := stmt.Scan(&ChannelId, &LinkId); err != nil {
return err
@ -292,12 +292,12 @@ func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
for stmt.Next() {
var (
UserId int64
UserName string
UserId int64
UserName string
SHA1Password string
LastChannel int
Texture []byte
LastActive int64
LastChannel int
Texture []byte
LastActive int64
)
err = stmt.Scan(&UserId, &UserName, &SHA1Password, &LastChannel, &Texture, &LastActive)
@ -340,7 +340,7 @@ func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
for stmt.Next() {
var (
Key int
Key int
Value string
)
@ -355,7 +355,7 @@ func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
case UserInfoComment:
// unhandled
case UserInfoHash:
user.CertHash = "sha1-" + Value
user.CertHash = Value
case UserInfoLastActive:
// not a kv-pair (trigger)
case UserInfoPassword:
@ -366,7 +366,5 @@ func populateUsers(server *Server, db *sqlite.Conn) (err os.Error) {
}
}
return
}

View file

@ -104,16 +104,7 @@ func NewServer(id int64, addr string, port int) (s *Server, err os.Error) {
s.MaxUsers = 10
s.Channels = make(map[int]*Channel)
s.root = s.NewChannel(0, "Root")
/*
err = s.addChannelsFromDB(0)
if err != nil {
return nil, err
}
*/
s.aclcache = NewACLCache()
return
@ -122,7 +113,7 @@ func NewServer(id int64, addr string, port int) (s *Server, err os.Error) {
// 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
}
@ -174,7 +165,7 @@ func (server *Server) NewClient(conn net.Conn) (err os.Error) {
client.msgchan = make(chan *Message)
client.udprecv = make(chan []byte)
client.UserId = -1
client.user = nil
go client.receiver()
go client.udpreceiver()
@ -334,10 +325,47 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
if len(state.PeerCertificates) > 0 {
hash := sha1.New()
hash.Write(state.PeerCertificates[0].Raw)
client.Hash = hex.EncodeToString(hash.Sum())
sum := hash.Sum()
client.CertHash = hex.EncodeToString(sum)
}
log.Printf("hash=%s", client.Hash)
if client.Username == "SuperUser" {
if auth.Password == nil {
client.RejectAuth("WrongUserPW", "")
return
} else {
if server.CheckSuperUserPassword(*auth.Password) {
client.superUser = true
} else {
client.RejectAuth("WrongUserPW", "")
return
}
}
} else {
// First look up registration by name.
user, exists := server.UserNameMap[client.Username]
if exists {
if user.CertHash == client.CertHash {
client.user = user
} else {
client.Panic("Invalid cert hash for user")
return
}
}
// Name matching didn't do. Try matching by certificate.
if client.user == nil {
user, exists := server.UserCertMap[client.CertHash]
if exists {
client.user = user
}
}
// Found a user for this guy
if client.user != nil {
log.Printf("Client authenticated as %v", client.user.Name)
}
}
// Setup the cryptstate for the client.
client.crypt, err = cryptstate.New()
@ -383,29 +411,13 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
server.hclients[host] = append(server.hclients[host], client)
server.hmutex.Unlock()
// SuperUser login check
if client.Username == "SuperUser" {
// No password specified
if auth.Password == nil {
client.RejectAuth("WrongUserPW", "")
return
} else {
if server.CheckSuperUserPassword(*auth.Password) {
client.UserId = 0
} else {
client.RejectAuth("WrongUserPW", "")
return
}
}
}
userstate := &mumbleproto.UserState{
Session: proto.Uint32(client.Session),
Name: proto.String(client.Username),
ChannelId: proto.Uint32(0),
}
if client.UserId >= 0 {
userstate.UserId = proto.Uint32(uint32(client.UserId))
if client.IsRegistered() {
userstate.UserId = proto.Uint32(uint32(client.UserId()))
}
server.userEnterChannel(client, server.root, userstate)
if err := server.broadcastProtoMessage(MessageUserState, userstate); err != nil {
@ -417,7 +429,7 @@ func (server *Server) handleAuthenticate(client *Client, msg *Message) {
sync := &mumbleproto.ServerSync{}
sync.Session = proto.Uint32(client.Session)
sync.MaxBandwidth = proto.Uint32(server.MaxBandwidth)
if client.UserId == 0 {
if client.IsSuperUser() {
sync.Permissions = proto.Uint64(uint64(AllPermissions))
} else {
server.HasPermission(client, server.root, EnterPermission)
@ -532,7 +544,7 @@ func (server *Server) sendUserList(client *Client) {
// Send a client its permissions for channel.
func (server *Server) sendClientPermissions(client *Client, channel *Channel) {
// No caching for SuperUser
if client.UserId == 0 {
if client.IsSuperUser() {
return
}

View file

@ -33,7 +33,7 @@ func NewUser(id uint32, name string) (user *User, err os.Error) {
}
return &User{
Id: id,
Id: id,
Name: name,
}, nil
},nil
}