mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-22 18:52:41 +01:00
fix #331
This commit is contained in:
parent
07bb38ecdf
commit
938ce7e435
@ -18,20 +18,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExpandUserHost takes a userhost, and returns an expanded version.
|
|
||||||
func ExpandUserHost(userhost string) (expanded string) {
|
|
||||||
expanded = userhost
|
|
||||||
// fill in missing wildcards for nicks
|
|
||||||
//TODO(dan): this would fail with dan@lol, fix that.
|
|
||||||
if !strings.Contains(expanded, "!") {
|
|
||||||
expanded += "!*"
|
|
||||||
}
|
|
||||||
if !strings.Contains(expanded, "@") {
|
|
||||||
expanded += "@*"
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ClientManager keeps track of clients by nick, enforcing uniqueness of casefolded nicks
|
// ClientManager keeps track of clients by nick, enforcing uniqueness of casefolded nicks
|
||||||
type ClientManager struct {
|
type ClientManager struct {
|
||||||
sync.RWMutex // tier 2
|
sync.RWMutex // tier 2
|
||||||
@ -241,7 +227,7 @@ func (clients *ClientManager) AllWithCapsNotify(capabs ...caps.Capability) (sess
|
|||||||
func (clients *ClientManager) FindAll(userhost string) (set ClientSet) {
|
func (clients *ClientManager) FindAll(userhost string) (set ClientSet) {
|
||||||
set = make(ClientSet)
|
set = make(ClientSet)
|
||||||
|
|
||||||
userhost, err := Casefold(ExpandUserHost(userhost))
|
userhost, err := CanonicalizeMaskWildcard(userhost)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return set
|
return set
|
||||||
}
|
}
|
||||||
|
@ -1372,10 +1372,11 @@ func killHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Resp
|
|||||||
// KLINE [ANDKILL] [MYSELF] [duration] <mask> [ON <server>] [reason [| oper reason]]
|
// KLINE [ANDKILL] [MYSELF] [duration] <mask> [ON <server>] [reason [| oper reason]]
|
||||||
// KLINE LIST
|
// KLINE LIST
|
||||||
func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
|
details := client.Details()
|
||||||
// check oper permissions
|
// check oper permissions
|
||||||
oper := client.Oper()
|
oper := client.Oper()
|
||||||
if oper == nil || !oper.Class.Capabilities["oper:local_ban"] {
|
if oper == nil || !oper.Class.Capabilities["oper:local_ban"] {
|
||||||
rb.Add(nil, server.name, ERR_NOPRIVS, client.nick, msg.Command, client.t("Insufficient oper privs"))
|
rb.Add(nil, server.name, ERR_NOPRIVS, details.nick, msg.Command, client.t("Insufficient oper privs"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1421,31 +1422,31 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
|||||||
|
|
||||||
// get mask
|
// get mask
|
||||||
if len(msg.Params) < currentArg+1 {
|
if len(msg.Params) < currentArg+1 {
|
||||||
rb.Add(nil, server.name, ERR_NEEDMOREPARAMS, client.nick, msg.Command, client.t("Not enough parameters"))
|
rb.Add(nil, server.name, ERR_NEEDMOREPARAMS, details.nick, msg.Command, client.t("Not enough parameters"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
mask := strings.ToLower(msg.Params[currentArg])
|
mask := msg.Params[currentArg]
|
||||||
currentArg++
|
currentArg++
|
||||||
|
|
||||||
// check mask
|
// check mask
|
||||||
if !strings.Contains(mask, "!") && !strings.Contains(mask, "@") {
|
mask, err = CanonicalizeMaskWildcard(mask)
|
||||||
mask = mask + "!*@*"
|
if err != nil {
|
||||||
} else if !strings.Contains(mask, "@") {
|
rb.Add(nil, server.name, ERR_UNKNOWNERROR, details.nick, msg.Command, client.t("Erroneous nickname"))
|
||||||
mask = mask + "@*"
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
matcher := ircmatch.MakeMatch(mask)
|
matcher := ircmatch.MakeMatch(mask)
|
||||||
|
|
||||||
for _, clientMask := range client.AllNickmasks() {
|
for _, clientMask := range client.AllNickmasks() {
|
||||||
if !klineMyself && matcher.Match(clientMask) {
|
if !klineMyself && matcher.Match(clientMask) {
|
||||||
rb.Add(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, client.t("This ban matches you. To KLINE yourself, you must use the command: /KLINE MYSELF <arguments>"))
|
rb.Add(nil, server.name, ERR_UNKNOWNERROR, details.nick, msg.Command, client.t("This ban matches you. To KLINE yourself, you must use the command: /KLINE MYSELF <arguments>"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// check remote
|
// check remote
|
||||||
if len(msg.Params) > currentArg && msg.Params[currentArg] == "ON" {
|
if len(msg.Params) > currentArg && msg.Params[currentArg] == "ON" {
|
||||||
rb.Add(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, client.t("Remote servers not yet supported"))
|
rb.Add(nil, server.name, ERR_UNKNOWNERROR, details.nick, msg.Command, client.t("Remote servers not yet supported"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1467,10 +1468,10 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
|||||||
var snoDescription string
|
var snoDescription string
|
||||||
if duration != 0 {
|
if duration != 0 {
|
||||||
rb.Notice(fmt.Sprintf(client.t("Added temporary (%[1]s) K-Line for %[2]s"), duration.String(), mask))
|
rb.Notice(fmt.Sprintf(client.t("Added temporary (%[1]s) K-Line for %[2]s"), duration.String(), mask))
|
||||||
snoDescription = fmt.Sprintf(ircfmt.Unescape("%s [%s]$r added temporary (%s) K-Line for %s"), client.nick, operName, duration.String(), mask)
|
snoDescription = fmt.Sprintf(ircfmt.Unescape("%s [%s]$r added temporary (%s) K-Line for %s"), details.nick, operName, duration.String(), mask)
|
||||||
} else {
|
} else {
|
||||||
rb.Notice(fmt.Sprintf(client.t("Added K-Line for %s"), mask))
|
rb.Notice(fmt.Sprintf(client.t("Added K-Line for %s"), mask))
|
||||||
snoDescription = fmt.Sprintf(ircfmt.Unescape("%s [%s]$r added K-Line for %s"), client.nick, operName, mask)
|
snoDescription = fmt.Sprintf(ircfmt.Unescape("%s [%s]$r added K-Line for %s"), details.nick, operName, mask)
|
||||||
}
|
}
|
||||||
server.snomasks.Send(sno.LocalXline, snoDescription)
|
server.snomasks.Send(sno.LocalXline, snoDescription)
|
||||||
|
|
||||||
@ -1501,7 +1502,7 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *Res
|
|||||||
|
|
||||||
// send snomask
|
// send snomask
|
||||||
sort.Strings(killedClientNicks)
|
sort.Strings(killedClientNicks)
|
||||||
server.snomasks.Send(sno.LocalKills, fmt.Sprintf(ircfmt.Unescape("%s [%s] killed %d clients with a KLINE $c[grey][$r%s$c[grey]]"), client.nick, operName, len(killedClientNicks), strings.Join(killedClientNicks, ", ")))
|
server.snomasks.Send(sno.LocalKills, fmt.Sprintf(ircfmt.Unescape("%s [%s] killed %d clients with a KLINE $c[grey][$r%s$c[grey]]"), details.nick, operName, len(killedClientNicks), strings.Join(killedClientNicks, ", ")))
|
||||||
}
|
}
|
||||||
|
|
||||||
return killClient
|
return killClient
|
||||||
@ -2486,31 +2487,31 @@ func unDLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *R
|
|||||||
|
|
||||||
// UNKLINE <mask>
|
// UNKLINE <mask>
|
||||||
func unKLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
func unKLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage, rb *ResponseBuffer) bool {
|
||||||
|
details := client.Details()
|
||||||
// check oper permissions
|
// check oper permissions
|
||||||
oper := client.Oper()
|
oper := client.Oper()
|
||||||
if oper == nil || !oper.Class.Capabilities["oper:local_unban"] {
|
if oper == nil || !oper.Class.Capabilities["oper:local_unban"] {
|
||||||
rb.Add(nil, server.name, ERR_NOPRIVS, client.nick, msg.Command, client.t("Insufficient oper privs"))
|
rb.Add(nil, server.name, ERR_NOPRIVS, details.nick, msg.Command, client.t("Insufficient oper privs"))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// get host
|
// get host
|
||||||
mask := msg.Params[0]
|
mask := msg.Params[0]
|
||||||
|
mask, err := CanonicalizeMaskWildcard(mask)
|
||||||
if !strings.Contains(mask, "!") && !strings.Contains(mask, "@") {
|
if err != nil {
|
||||||
mask = mask + "!*@*"
|
rb.Add(nil, server.name, ERR_UNKNOWNERROR, details.nick, msg.Command, client.t("Erroneous nickname"))
|
||||||
} else if !strings.Contains(mask, "@") {
|
return false
|
||||||
mask = mask + "@*"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := server.klines.RemoveMask(mask)
|
err = server.klines.RemoveMask(mask)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
rb.Add(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, fmt.Sprintf(client.t("Could not remove ban [%s]"), err.Error()))
|
rb.Add(nil, server.name, ERR_UNKNOWNERROR, details.nick, msg.Command, fmt.Sprintf(client.t("Could not remove ban [%s]"), err.Error()))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
rb.Notice(fmt.Sprintf(client.t("Removed K-Line for %s"), mask))
|
rb.Notice(fmt.Sprintf(client.t("Removed K-Line for %s"), mask))
|
||||||
server.snomasks.Send(sno.LocalXline, fmt.Sprintf(ircfmt.Unescape("%s$r removed K-Line for %s"), client.nick, mask))
|
server.snomasks.Send(sno.LocalXline, fmt.Sprintf(ircfmt.Unescape("%s$r removed K-Line for %s"), details.nick, mask))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package irc
|
package irc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/oragono/confusables"
|
"github.com/oragono/confusables"
|
||||||
@ -157,3 +158,55 @@ func Skeleton(name string) (string, error) {
|
|||||||
// pass PRECIS --- we are just further canonicalizing the skeleton.
|
// pass PRECIS --- we are just further canonicalizing the skeleton.
|
||||||
return cases.Lower(language.Und).String(name), nil
|
return cases.Lower(language.Und).String(name), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// maps a nickmask fragment to an expanded, casefolded wildcard:
|
||||||
|
// Shivaram@good-fortune -> *!shivaram@good-fortune
|
||||||
|
// EDMUND -> edmund!*@*
|
||||||
|
func CanonicalizeMaskWildcard(userhost string) (expanded string, err error) {
|
||||||
|
var nick, user, host string
|
||||||
|
bangIndex := strings.IndexByte(userhost, '!')
|
||||||
|
strudelIndex := strings.IndexByte(userhost, '@')
|
||||||
|
|
||||||
|
if bangIndex != -1 && bangIndex < strudelIndex {
|
||||||
|
nick = userhost[:bangIndex]
|
||||||
|
user = userhost[bangIndex+1 : strudelIndex]
|
||||||
|
host = userhost[strudelIndex+1:]
|
||||||
|
} else if bangIndex != -1 && strudelIndex == -1 {
|
||||||
|
nick = userhost[:bangIndex]
|
||||||
|
user = userhost[bangIndex+1:]
|
||||||
|
} else if bangIndex != -1 && strudelIndex < bangIndex {
|
||||||
|
// @ before !, fail
|
||||||
|
return "", errNicknameInvalid
|
||||||
|
} else if bangIndex == -1 && strudelIndex != -1 {
|
||||||
|
user = userhost[:strudelIndex]
|
||||||
|
host = userhost[strudelIndex+1:]
|
||||||
|
} else if bangIndex == -1 && strudelIndex == -1 {
|
||||||
|
nick = userhost
|
||||||
|
} else {
|
||||||
|
// shouldn't be possible
|
||||||
|
return "", errInvalidParams
|
||||||
|
}
|
||||||
|
|
||||||
|
if nick == "" {
|
||||||
|
nick = "*"
|
||||||
|
}
|
||||||
|
if nick != "*" {
|
||||||
|
nick, err = Casefold(nick)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if user == "" {
|
||||||
|
user = "*"
|
||||||
|
}
|
||||||
|
if user != "*" {
|
||||||
|
user = strings.ToLower(user)
|
||||||
|
}
|
||||||
|
if host == "" {
|
||||||
|
host = "*"
|
||||||
|
}
|
||||||
|
if host != "*" {
|
||||||
|
host = strings.ToLower(host)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s!%s@%s", nick, user, host), nil
|
||||||
|
}
|
||||||
|
@ -188,3 +188,27 @@ func TestSkeleton(t *testing.T) {
|
|||||||
// should not raise an error:
|
// should not raise an error:
|
||||||
skeleton("けらんぐ")
|
skeleton("けらんぐ")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCanonicalizeMaskWildcard(t *testing.T) {
|
||||||
|
tester := func(input, expected string, expectedErr error) {
|
||||||
|
out, err := CanonicalizeMaskWildcard(input)
|
||||||
|
if out != expected {
|
||||||
|
t.Errorf("expected %s to canonicalize to %s, instead %s", input, expected, out)
|
||||||
|
}
|
||||||
|
if err != expectedErr {
|
||||||
|
t.Errorf("expected %s to produce error %v, instead %v", input, expectedErr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tester("shivaram", "shivaram!*@*", nil)
|
||||||
|
tester("slingamn!shivaram", "slingamn!shivaram@*", nil)
|
||||||
|
tester("ברוך", "ברוך!*@*", nil)
|
||||||
|
tester("hacker@monad.io", "*!hacker@monad.io", nil)
|
||||||
|
tester("Evan!hacker@monad.io", "evan!hacker@monad.io", nil)
|
||||||
|
tester("РОТАТО!Potato", "ротато!potato@*", nil)
|
||||||
|
tester("tkadich*", "tkadich*!*@*", nil)
|
||||||
|
tester("SLINGAMN!*@*", "slingamn!*@*", nil)
|
||||||
|
tester("slingamn!shivaram*", "slingamn!shivaram*@*", nil)
|
||||||
|
tester("slingamn!", "slingamn!*@*", nil)
|
||||||
|
tester("shivaram*@good-fortune", "*!shivaram*@good-fortune", nil)
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user