Registration support.

This commit is contained in:
Mikkel Krautz 2011-04-28 00:18:03 +02:00
parent 95509f9138
commit 28a74743a6
4 changed files with 130 additions and 17 deletions

View file

@ -60,6 +60,7 @@ type Client struct {
Username string Username string
Session uint32 Session uint32
CertHash string CertHash string
Email string
Tokens []string Tokens []string
Channel *Channel Channel *Channel
SelfMute bool SelfMute bool

View file

@ -292,6 +292,9 @@ func NewServerFromFrozen(filename string) (s *Server, err os.Error) {
u.LastActive = fu.LastActive u.LastActive = fu.LastActive
s.Users[u.Id] = u s.Users[u.Id] = u
if u.Id > s.nextUserId {
s.nextUserId = u.Id + 1
}
s.UserNameMap[u.Name] = u s.UserNameMap[u.Name] = u
if len(u.CertHash) > 0 { if len(u.CertHash) > 0 {
s.UserCertMap[u.CertHash] = u s.UserCertMap[u.CertHash] = u

View file

@ -601,21 +601,19 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
if userstate.UserId != nil { if userstate.UserId != nil {
// If user == actor, check for SelfRegisterPermission on root channel. // If user == actor, check for SelfRegisterPermission on root channel.
// If user != actor, check for RegisterPermission permission on root channel. // If user != actor, check for RegisterPermission permission on root channel.
permCheck := Permission(NonePermission) perm := Permission(RegisterPermission)
uid := *userstate.UserId if actor == target {
if target == actor { perm = Permission(SelfRegisterPermission)
permCheck = SelfRegisterPermission
} else {
permCheck = RegisterPermission
} }
if uid >= 0 || !server.HasPermission(actor, server.root, SelfRegisterPermission) {
client.sendPermissionDenied(actor, server.root, permCheck) if target.IsRegistered() || !server.HasPermission(actor, server.root, perm) {
client.sendPermissionDenied(actor, server.root, perm)
return return
} }
// We can't register a user with an empty hash.
if len(target.CertHash) == 0 { if len(target.CertHash) == 0 {
client.sendPermissionDeniedTypeUser("MissingCertificate", target) client.sendPermissionDeniedTypeUser("MissingCertificate", target)
return
} }
} }
@ -733,11 +731,18 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
broadcast = true broadcast = true
} }
userRegistrationChanged := false
if userstate.UserId != nil { if userstate.UserId != nil {
// fixme(mkrautz): Registration is currently unhandled. uid := server.RegisterClient(client)
log.Printf("handleUserState: (Self)Register not implemented yet!") if uid > 0 {
userstate.UserId = proto.Uint32(uid)
client.user = server.Users[uid]
userRegistrationChanged = true
} else {
userstate.UserId = nil userstate.UserId = nil
} }
broadcast = true
}
if userstate.ChannelId != nil { if userstate.ChannelId != nil {
channel, ok := server.Channels[int(*userstate.ChannelId)] channel, ok := server.Channels[int(*userstate.ChannelId)]
@ -799,6 +804,10 @@ func (server *Server) handleUserStateMessage(client *Client, msg *Message) {
userstate.CommentHash = nil userstate.CommentHash = nil
} }
if userRegistrationChanged {
server.ClearACLCache()
}
err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool { err := server.broadcastProtoMessageWithPredicate(MessageUserState, userstate, func(client *Client) bool {
return client.Version >= 0x10203 return client.Version >= 0x10203
}) })
@ -1198,3 +1207,55 @@ func (server *Server) handleRequestBlob(client *Client, msg *Message) {
} }
} }
} }
// User list query, user rename, user de-register
func (server *Server) handleUserList(client *Client, msg *Message) {
userlist := &mumbleproto.UserList{}
err := proto.Unmarshal(msg.buf, userlist)
if err != nil {
client.Panic(err.String())
return
}
// Only users who are allowed to register other users can access the user list.
if !server.HasPermission(client, server.root, RegisterPermission) {
client.sendPermissionDenied(client, server.root, RegisterPermission)
return
}
// Query user list
if len(userlist.Users) == 0 {
for uid, user := range server.Users {
if uid == 0 {
continue
}
userlist.Users = append(userlist.Users, &mumbleproto.UserList_User{
UserId: proto.Uint32(uid),
Name: proto.String(user.Name),
})
}
if err := client.sendProtoMessage(MessageUserList, userlist); err != nil {
client.Panic(err.String())
return
}
// Rename, registration removal
} else {
for _, listUser := range userlist.Users {
uid := *listUser.UserId
if uid == 0 {
continue
}
// De-register a user
if listUser.Name == nil {
server.RemoveRegistration(uid)
// Rename user
} else {
// todo(mkrautz): Validate name.
user, ok := server.Users[uid]
if ok {
user.Name = *listUser.Name
}
}
}
}
}

View file

@ -84,6 +84,7 @@ type Server struct {
Users map[uint32]*User Users map[uint32]*User
UserCertMap map[string]*User UserCertMap map[string]*User
UserNameMap map[string]*User UserNameMap map[string]*User
nextUserId uint32
// ACL cache // ACL cache
aclcache ACLCache aclcache ACLCache
@ -537,6 +538,11 @@ func (server *Server) finishAuthenticate(client *Client) {
Name: proto.String(client.ShownName()), Name: proto.String(client.ShownName()),
ChannelId: proto.Uint32(0), ChannelId: proto.Uint32(0),
} }
if len(client.CertHash) > 0 {
userstate.Hash = proto.String(client.CertHash)
}
if client.IsRegistered() { if client.IsRegistered() {
userstate.UserId = proto.Uint32(uint32(client.UserId())) userstate.UserId = proto.Uint32(uint32(client.UserId()))
@ -681,6 +687,10 @@ func (server *Server) sendUserList(client *Client) {
ChannelId: proto.Uint32(uint32(connectedClient.Channel.Id)), ChannelId: proto.Uint32(uint32(connectedClient.Channel.Id)),
} }
if len(connectedClient.CertHash) > 0 {
userstate.Hash = connectedClient.CertHash
}
if connectedClient.IsRegistered() { if connectedClient.IsRegistered() {
userstate.UserId = proto.Uint32(uint32(connectedClient.UserId())) userstate.UserId = proto.Uint32(uint32(connectedClient.UserId()))
@ -709,10 +719,6 @@ func (server *Server) sendUserList(client *Client) {
userstate.Comment = proto.String(string(buf)) userstate.Comment = proto.String(string(buf))
} }
} }
if len(connectedClient.user.CertHash) > 0 {
userstate.Hash = proto.String(connectedClient.user.CertHash)
}
} }
if connectedClient.Mute { if connectedClient.Mute {
@ -820,7 +826,7 @@ func (server *Server) handleIncomingMessage(client *Client, msg *Message) {
case MessageContextAction: case MessageContextAction:
log.Printf("MessageContextAction from client") log.Printf("MessageContextAction from client")
case MessageUserList: case MessageUserList:
log.Printf("MessageUserList from client") server.handleUserList(msg.client, msg)
case MessageVoiceTarget: case MessageVoiceTarget:
log.Printf("MessageVoiceTarget from client") log.Printf("MessageVoiceTarget from client")
case MessagePermissionQuery: case MessagePermissionQuery:
@ -1003,6 +1009,48 @@ func (s *Server) FreezeServer() io.ReadCloser {
return fr.readCloser return fr.readCloser
} }
// Register a client on the server.
func (s *Server) RegisterClient(client *Client) (uid uint32) {
// Increment nextUserId only if registration succeeded.
defer func() {
if uid > 0 {
s.nextUserId += 1
}
}()
user, err := NewUser(s.nextUserId, client.Username)
if err != nil {
return 0
}
// Grumble can only register users with certificates.
if len(client.CertHash) == 0 {
return 0
}
user.Email = client.Email
user.CertHash = client.CertHash
uid = s.nextUserId
s.Users[uid] = user
s.UserCertMap[client.CertHash] = user
s.UserNameMap[client.Username] = user
return uid
}
// Remove a registered user.
func (s *Server) RemoveRegistration(uid uint32) (err os.Error) {
user, ok := s.Users[uid]
if !ok {
return os.NewError("Unknown user ID")
}
s.Users[uid] = nil, false
s.UserCertMap[user.CertHash] = nil, false
s.UserNameMap[user.Name] = nil, false
return nil
}
// The accept loop of the server. // The accept loop of the server.
func (s *Server) ListenAndMurmur() { func (s *Server) ListenAndMurmur() {
// Launch the event handler goroutine // Launch the event handler goroutine