fix some KICK issues

reported by bogdomania

1. KICK without privileges incorrectly returned ERR_CANNOTSENDTOCHAN
2. Halfops should be able to kick voice and unprivileged, but not other halfops
This commit is contained in:
Shivaram Lingamneni 2019-02-13 14:38:10 -05:00
parent 7438c89d6b
commit b7ec121c19
1 changed files with 26 additions and 25 deletions

View File

@ -241,12 +241,7 @@ func (channel *Channel) Names(client *Client, rb *ResponseBuffer) {
rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list")) rb.Add(nil, client.server.name, RPL_ENDOFNAMES, client.nick, channel.name, client.t("End of NAMES list"))
} }
// ClientIsAtLeast returns whether the client has at least the given channel privilege. func channelUserModeIsAtLeast(clientModes *modes.ModeSet, permission modes.Mode) bool {
func (channel *Channel) ClientIsAtLeast(client *Client, permission modes.Mode) bool {
channel.stateMutex.RLock()
clientModes := channel.members[client]
channel.stateMutex.RUnlock()
if clientModes == nil { if clientModes == nil {
return false return false
} }
@ -264,6 +259,14 @@ func (channel *Channel) ClientIsAtLeast(client *Client, permission modes.Mode) b
return false return false
} }
// ClientIsAtLeast returns whether the client has at least the given channel privilege.
func (channel *Channel) ClientIsAtLeast(client *Client, permission modes.Mode) bool {
channel.stateMutex.RLock()
clientModes := channel.members[client]
channel.stateMutex.RUnlock()
return channelUserModeIsAtLeast(clientModes, permission)
}
func (channel *Channel) ClientPrefixes(client *Client, isMultiPrefix bool) string { func (channel *Channel) ClientPrefixes(client *Client, isMultiPrefix bool) string {
channel.stateMutex.RLock() channel.stateMutex.RLock()
defer channel.stateMutex.RUnlock() defer channel.stateMutex.RUnlock()
@ -277,24 +280,26 @@ func (channel *Channel) ClientPrefixes(client *Client, isMultiPrefix bool) strin
func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool { func (channel *Channel) ClientHasPrivsOver(client *Client, target *Client) bool {
channel.stateMutex.RLock() channel.stateMutex.RLock()
defer channel.stateMutex.RUnlock()
clientModes := channel.members[client] clientModes := channel.members[client]
targetModes := channel.members[target] targetModes := channel.members[target]
result := false channel.stateMutex.RUnlock()
for _, mode := range modes.ChannelPrivModes {
if clientModes.HasMode(mode) { if clientModes.HasMode(modes.ChannelFounder) {
result = true // founder can kick anyone
return true
} else if clientModes.HasMode(modes.ChannelAdmin) {
// admins cannot kick other admins // admins cannot kick other admins
if mode == modes.ChannelAdmin && targetModes.HasMode(modes.ChannelAdmin) { return !channelUserModeIsAtLeast(targetModes, modes.ChannelAdmin)
result = false } else if clientModes.HasMode(modes.ChannelOperator) {
// operators *can* kick other operators
return !channelUserModeIsAtLeast(targetModes, modes.ChannelAdmin)
} else if clientModes.HasMode(modes.Halfop) {
// halfops cannot kick other halfops
return !channelUserModeIsAtLeast(targetModes, modes.Halfop)
} else {
// voice and unprivileged cannot kick anyone
return false
} }
break
} else if targetModes.HasMode(mode) {
break
}
}
return result
} }
func (channel *Channel) hasClient(client *Client) bool { func (channel *Channel) hasClient(client *Client) bool {
@ -952,10 +957,6 @@ func (channel *Channel) Kick(client *Client, target *Client, comment string, rb
rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel")) rb.Add(nil, client.server.name, ERR_NOTONCHANNEL, channel.name, client.t("You're not on that channel"))
return return
} }
if !channel.ClientIsAtLeast(client, modes.ChannelOperator) {
rb.Add(nil, client.server.name, ERR_CANNOTSENDTOCHAN, channel.name, client.t("Cannot send to channel"))
return
}
if !channel.hasClient(target) { if !channel.hasClient(target) {
rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.nick, channel.name, client.t("They aren't on that channel")) rb.Add(nil, client.server.name, ERR_USERNOTINCHANNEL, client.nick, channel.name, client.t("They aren't on that channel"))
return return