Merge pull request #166 from slingamn/banlist.3

allow non-operators to list bans
This commit is contained in:
Daniel Oaks 2017-11-17 16:09:21 +10:00 committed by GitHub
commit bec050208d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 47 deletions

View File

@ -240,7 +240,7 @@ func NewUserMaskSet() *UserMaskSet {
} }
// Add adds the given mask to this set. // Add adds the given mask to this set.
func (set *UserMaskSet) Add(mask string) bool { func (set *UserMaskSet) Add(mask string) (added bool) {
casefoldedMask, err := Casefold(mask) casefoldedMask, err := Casefold(mask)
if err != nil { if err != nil {
log.Println(fmt.Sprintf("ERROR: Could not add mask to usermaskset: [%s]", mask)) log.Println(fmt.Sprintf("ERROR: Could not add mask to usermaskset: [%s]", mask))
@ -248,16 +248,16 @@ func (set *UserMaskSet) Add(mask string) bool {
} }
set.Lock() set.Lock()
already := set.masks[casefoldedMask] added = !set.masks[casefoldedMask]
if added {
set.masks[casefoldedMask] = true set.masks[casefoldedMask] = true
}
set.Unlock() set.Unlock()
if already { if added {
return false
} else {
set.setRegexp() set.setRegexp()
return true
} }
return
} }
// AddAll adds the given masks to this set. // AddAll adds the given masks to this set.
@ -271,23 +271,25 @@ func (set *UserMaskSet) AddAll(masks []string) (added bool) {
} }
set.masks[mask] = true set.masks[mask] = true
} }
if added {
set.setRegexp() set.setRegexp()
}
return return
} }
// Remove removes the given mask from this set. // Remove removes the given mask from this set.
func (set *UserMaskSet) Remove(mask string) bool { func (set *UserMaskSet) Remove(mask string) (removed bool) {
set.Lock() set.Lock()
already := !set.masks[mask] removed = set.masks[mask]
if removed {
delete(set.masks, mask) delete(set.masks, mask)
}
set.Unlock() set.Unlock()
if !already { if removed {
return false
} else {
set.setRegexp() set.setRegexp()
return true
} }
return
} }
// Match matches the given n!u@h. // Match matches the given n!u@h.

View File

@ -484,10 +484,40 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
applied := make(ModeChanges, 0) applied := make(ModeChanges, 0)
isListOp := func(change ModeChange) bool {
return (change.op == List) || (change.arg == "")
}
hasPrivs := func(change ModeChange) bool {
if isSamode {
return true
}
switch change.mode {
case ChannelFounder, ChannelAdmin, ChannelOperator, Halfop, Voice:
// Admins can't give other people Admin or remove it from others
if change.mode == ChannelAdmin {
return false
}
if change.op == List {
return true
}
cfarg, _ := CasefoldName(change.arg)
if change.op == Remove && cfarg == client.nickCasefolded {
// "There is no restriction, however, on anyone `deopping' themselves"
// <https://tools.ietf.org/html/rfc2812#section-3.1.5>
return true
}
return channel.ClientIsAtLeast(client, change.mode)
case BanMask:
// #163: allow unprivileged users to list ban masks
return clientIsOp || isListOp(change)
default:
return clientIsOp
}
}
for _, change := range changes { for _, change := range changes {
// chan priv modes are checked specially so ignore them if !hasPrivs(change) {
// means regular users can't view ban/except lists... but I'm not worried about that
if !isSamode && ChannelModePrefixes[change.mode] == "" && !clientIsOp {
if !alreadySentPrivError { if !alreadySentPrivError {
alreadySentPrivError = true alreadySentPrivError = true
client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, "You're not a channel operator") client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, "You're not a channel operator")
@ -497,15 +527,13 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
switch change.mode { switch change.mode {
case BanMask, ExceptMask, InviteMask: case BanMask, ExceptMask, InviteMask:
mask := change.arg if isListOp(change) {
if (change.op == List) || (mask == "") {
channel.ShowMaskList(client, change.mode) channel.ShowMaskList(client, change.mode)
continue continue
} }
// confirm mask looks valid // confirm mask looks valid
mask, err := Casefold(mask) mask, err := Casefold(change.arg)
if err != nil { if err != nil {
continue continue
} }
@ -566,31 +594,6 @@ func (channel *Channel) ApplyChannelModeChanges(client *Client, isSamode bool, c
if change.op == List { if change.op == List {
continue continue
} }
// make sure client has privs to edit the given prefix
hasPrivs := isSamode
// Admins can't give other people Admin or remove it from others,
// standard for that channel mode, we worry about this later
if !hasPrivs && change.mode != ChannelAdmin {
hasPrivs = channel.ClientIsAtLeast(client, change.mode)
}
casefoldedName, err := CasefoldName(change.arg)
if err != nil {
continue
}
if !hasPrivs {
if change.op == Remove && casefoldedName == client.nickCasefolded {
// success!
} else {
if !alreadySentPrivError {
alreadySentPrivError = true
client.Send(nil, client.server.name, ERR_CHANOPRIVSNEEDED, channel.name, "You're not a channel operator")
}
continue
}
}
change := channel.applyModeMemberNoMutex(client, change.mode, change.op, change.arg) change := channel.applyModeMemberNoMutex(client, change.mode, change.op, change.arg)
if change != nil { if change != nil {