3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-10 22:19:31 +01:00

xline: Add ANDKILL param to kill all matching clients

This commit is contained in:
Daniel Oaks 2017-05-24 00:58:36 -06:00
parent 3101f16478
commit ebb9d629d7
5 changed files with 88 additions and 10 deletions

View File

@ -137,6 +137,11 @@ func NewClient(server *Server, conn net.Conn, isTLS bool) *Client {
return client return client
} }
// IP returns the IP address of this client.
func (client *Client) IP() net.IP {
return net.ParseIP(IPString(client.socket.conn.RemoteAddr()))
}
// //
// command goroutine // command goroutine
// //
@ -475,7 +480,7 @@ func (client *Client) destroy() {
friends.Remove(client) friends.Remove(client)
// remove from connection limits // remove from connection limits
ipaddr := net.ParseIP(IPString(client.socket.conn.RemoteAddr())) ipaddr := client.IP()
// this check shouldn't be required but eh // this check shouldn't be required but eh
if ipaddr != nil { if ipaddr != nil {
client.server.connectionLimitsMutex.Lock() client.server.connectionLimitsMutex.Lock()

View File

@ -183,7 +183,7 @@ func (dm *DLineManager) CheckIP(addr net.IP) (isBanned bool, info *IPBanInfo) {
return false, nil return false, nil
} }
// DLINE [MYSELF] [duration] <ip>/<net> [ON <server>] [reason [| oper reason]] // DLINE [ANDKILL] [MYSELF] [duration] <ip>/<net> [ON <server>] [reason [| oper reason]]
func dlineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { func dlineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
// check oper permissions // check oper permissions
if !client.class.Capabilities["oper:local_ban"] { if !client.class.Capabilities["oper:local_ban"] {
@ -193,6 +193,13 @@ func dlineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
currentArg := 0 currentArg := 0
// when setting a ban, if they say "ANDKILL" we should also kill all users who match it
var andKill bool
if len(msg.Params) > currentArg+1 && strings.ToLower(msg.Params[currentArg]) == "andkill" {
andKill = true
currentArg++
}
// when setting a ban that covers the oper's current connection, we require them to say // when setting a ban that covers the oper's current connection, we require them to say
// "DLINE MYSELF" so that we're sure they really mean it. // "DLINE MYSELF" so that we're sure they really mean it.
var dlineMyself bool var dlineMyself bool
@ -232,13 +239,13 @@ func dlineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
if hostNet == nil { if hostNet == nil {
hostString = hostAddr.String() hostString = hostAddr.String()
if !dlineMyself && hostAddr.Equal(net.ParseIP(IPString(client.socket.conn.RemoteAddr()))) { if !dlineMyself && hostAddr.Equal(client.IP()) {
client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, "This ban matches you. To DLINE yourself, you must use the command: /DLINE MYSELF <arguments>") client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, "This ban matches you. To DLINE yourself, you must use the command: /DLINE MYSELF <arguments>")
return false return false
} }
} else { } else {
hostString = hostNet.String() hostString = hostNet.String()
if !dlineMyself && hostNet.Contains(net.ParseIP(IPString(client.socket.conn.RemoteAddr()))) { if !dlineMyself && hostNet.Contains(client.IP()) {
client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, "This ban matches you. To DLINE yourself, you must use the command: /DLINE MYSELF <arguments>") client.Send(nil, server.name, ERR_UNKNOWNERROR, client.nick, msg.Command, "This ban matches you. To DLINE yourself, you must use the command: /DLINE MYSELF <arguments>")
return false return false
} }
@ -315,7 +322,37 @@ func dlineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
client.Notice(fmt.Sprintf("Added D-Line for %s", hostString)) client.Notice(fmt.Sprintf("Added D-Line for %s", hostString))
} }
return false var killClient bool
if andKill {
var clientsToKill []*Client
var toKill bool
server.clients.ByNickMutex.RLock()
for _, mcl := range server.clients.ByNick {
if hostNet == nil {
toKill = hostAddr.Equal(mcl.IP())
} else {
toKill = hostNet.Contains(mcl.IP())
}
if toKill {
clientsToKill = append(clientsToKill, mcl)
}
}
server.clients.ByNickMutex.RUnlock()
for _, mcl := range clientsToKill {
mcl.Quit(fmt.Sprintf("You have been banned from this server (%s)", reason))
if mcl == client {
killClient = true
} else {
// if mcl == client, we kill them below
mcl.destroy()
}
}
}
return killClient
} }
func unDLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { func unDLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {

View File

@ -145,7 +145,7 @@ Prints debug information about the IRCd. <option> can be one of:
}, },
"dline": { "dline": {
oper: true, oper: true,
text: `DLINE [MYSELF] [duration] <ip>/<net> [ON <server>] [reason [| oper reason]] text: `DLINE [ANDKILL] [MYSELF] [duration] <ip>/<net> [ON <server>] [reason [| oper reason]]
Bans an IP address or network from connecting to the server. If the duration is Bans an IP address or network from connecting to the server. If the duration is
given then only for that long. The reason is shown to the user themselves, but given then only for that long. The reason is shown to the user themselves, but
@ -154,6 +154,8 @@ operators getting info about the DLINEs that exist.
Bans are saved across subsequent launches of the server. Bans are saved across subsequent launches of the server.
"ANDKILL" means that all matching clients are also removed from the server.
"MYSELF" is required when the DLINE matches the address the person applying it is connected "MYSELF" is required when the DLINE matches the address the person applying it is connected
from. If "MYSELF" is not given, trying to DLINE yourself will result in an error. from. If "MYSELF" is not given, trying to DLINE yourself will result in an error.
@ -211,7 +213,7 @@ supplied.`,
}, },
"kline": { "kline": {
oper: true, oper: true,
text: `KLINE [MYSELF] [duration] <mask> [ON <server>] [reason [| oper reason]] text: `KLINE [ANDKILL] [MYSELF] [duration] <mask> [ON <server>] [reason [| oper reason]]
Bans a mask from connecting to the server. If the duration is given then only for that Bans a mask from connecting to the server. If the duration is given then only for that
long. The reason is shown to the user themselves, but everyone else will see a standard long. The reason is shown to the user themselves, but everyone else will see a standard
@ -219,6 +221,8 @@ message. The oper reason is shown to operators getting info about the KLINEs tha
Bans are saved across subsequent launches of the server. Bans are saved across subsequent launches of the server.
"ANDKILL" means that all matching clients are also removed from the server.
"MYSELF" is required when the KLINE matches the address the person applying it is connected "MYSELF" is required when the KLINE matches the address the person applying it is connected
from. If "MYSELF" is not given, trying to KLINE yourself will result in an error. from. If "MYSELF" is not given, trying to KLINE yourself will result in an error.

View File

@ -110,7 +110,7 @@ func (km *KLineManager) CheckMasks(masks ...string) (isBanned bool, info *IPBanI
return false, nil return false, nil
} }
// KLINE [MYSELF] [duration] <mask> [ON <server>] [reason [| oper reason]] // KLINE [ANDKILL] [MYSELF] [duration] <mask> [ON <server>] [reason [| oper reason]]
func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
// check oper permissions // check oper permissions
if !client.class.Capabilities["oper:local_ban"] { if !client.class.Capabilities["oper:local_ban"] {
@ -120,6 +120,13 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
currentArg := 0 currentArg := 0
// when setting a ban, if they say "ANDKILL" we should also kill all users who match it
var andKill bool
if len(msg.Params) > currentArg+1 && strings.ToLower(msg.Params[currentArg]) == "andkill" {
andKill = true
currentArg++
}
// when setting a ban that covers the oper's current connection, we require them to say // when setting a ban that covers the oper's current connection, we require them to say
// "KLINE MYSELF" so that we're sure they really mean it. // "KLINE MYSELF" so that we're sure they really mean it.
var klineMyself bool var klineMyself bool
@ -226,7 +233,32 @@ func klineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {
client.Notice(fmt.Sprintf("Added K-Line for %s", mask)) client.Notice(fmt.Sprintf("Added K-Line for %s", mask))
} }
return false var killClient bool
if andKill {
var clientsToKill []*Client
server.clients.ByNickMutex.RLock()
for _, mcl := range server.clients.ByNick {
for _, clientMask := range mcl.AllNickmasks() {
if matcher.Match(clientMask) {
clientsToKill = append(clientsToKill, mcl)
}
}
}
server.clients.ByNickMutex.RUnlock()
for _, mcl := range clientsToKill {
mcl.Quit(fmt.Sprintf("You have been banned from this server (%s)", reason))
if mcl == client {
killClient = true
} else {
// if mcl == client, we kill them below
mcl.destroy()
}
}
}
return killClient
} }
func unKLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool { func unKLineHandler(server *Server, client *Client, msg ircmsg.IrcMessage) bool {

View File

@ -1358,7 +1358,7 @@ func (server *Server) rehash() error {
server.clients.ByNickMutex.RLock() server.clients.ByNickMutex.RLock()
for _, client := range server.clients.ByNick { for _, client := range server.clients.ByNick {
ipaddr := net.ParseIP(IPString(client.socket.conn.RemoteAddr())) ipaddr := client.IP()
if ipaddr != nil { if ipaddr != nil {
server.connectionLimits.AddClient(ipaddr, true) server.connectionLimits.AddClient(ipaddr, true)
} }