3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-24 03:29:28 +01:00

bots: more validation in "MODE" to prevent bad things from happening

This adds a new "allow_forceset_usermodes" attribute to protocol modules, which determines whether the IRCd allows us to force usermode changes on other servers' clients.

Also, make sure our target is a valid nick/UID/channel, and that the parsed modes are not empty!
This commit is contained in:
James Lu 2015-09-14 17:44:07 -07:00
parent 78080bde6b
commit c5b6658200
3 changed files with 23 additions and 13 deletions

View File

@ -396,6 +396,9 @@ class Protocol():
self.casemapping = 'rfc1459' self.casemapping = 'rfc1459'
self.hook_map = {} self.hook_map = {}
# Whether the IRCd allows forcing user mode changes on other servers' clients.
self.allow_forceset_usermodes = False
class FakeProto(Protocol): class FakeProto(Protocol):
"""Dummy protocol module for testing purposes.""" """Dummy protocol module for testing purposes."""
def handle_events(self, data): def handle_events(self, data):

View File

@ -138,30 +138,34 @@ def kick(irc, source, args):
def mode(irc, source, args): def mode(irc, source, args):
"""<source> <target> <modes> """<source> <target> <modes>
Admin-only. Sets modes <modes> on <target> from <source>, where <source> is either the nick of a PyLink client, or the SID of a PyLink server.""" Admin-only. Sets modes <modes> on <target> from <source>, where <source> is either the nick of a PyLink client, or the SID of a PyLink server. <target> can be either a nick or a channel."""
utils.checkAuthenticated(irc, source, allowOper=False) utils.checkAuthenticated(irc, source, allowOper=False)
try: try:
modesource, target, modes = args[0], args[1], args[2:] modesource, target, modes = args[0], args[1], args[2:]
except IndexError: except IndexError:
irc.msg(source, 'Error: Not enough arguments. Needs 3: source nick, target, modes to set.') irc.msg(source, 'Error: Not enough arguments. Needs 3: source nick, target, modes to set.')
return return
if not modes: target = utils.nickToUid(irc, target) or target
irc.msg(source, "Error: No modes given to set!") if not (target in irc.users or target in irc.channels):
return
parsedmodes = utils.parseModes(irc, target, modes)
targetuid = utils.nickToUid(irc, target)
if targetuid:
target = targetuid
elif not utils.isChannel(target):
irc.msg(source, "Error: Invalid channel or nick %r." % target) irc.msg(source, "Error: Invalid channel or nick %r." % target)
return return
elif target in irc.users and not irc.proto.allow_forceset_usermodes:
irc.msg(source, "Error: this IRCd does not allow forcing user mode "
"changes on other servers' users!")
return
parsedmodes = utils.parseModes(irc, target, modes)
if not parsedmodes:
irc.msg(source, "Error: No valid modes were given.")
return
if utils.isInternalServer(irc, modesource): if utils.isInternalServer(irc, modesource):
# Setting modes from a server.
irc.proto.modeServer(modesource, target, parsedmodes) irc.proto.modeServer(modesource, target, parsedmodes)
irc.callHooks([modesource, 'PYLINK_BOTSPLUGIN_MODE', {'target': target, 'modes': parsedmodes, 'parse_as': 'MODE'}])
else: else:
sourceuid = utils.nickToUid(irc, modesource) # Setting modes from a client.
irc.proto.modeClient(sourceuid, target, parsedmodes) modesource = utils.nickToUid(irc, modesource)
irc.callHooks([sourceuid, 'PYLINK_BOTSPLUGIN_MODE', {'target': target, 'modes': parsedmodes, 'parse_as': 'MODE'}]) irc.proto.modeClient(modesource, target, parsedmodes)
irc.callHooks([modesource, 'PYLINK_BOTSPLUGIN_MODE',
{'target': target, 'modes': parsedmodes, 'parse_as': 'MODE'}])
@utils.add_cmd @utils.add_cmd
def msg(irc, source, args): def msg(irc, source, args):

View File

@ -27,6 +27,9 @@ class InspIRCdProtocol(TS6BaseProtocol):
self.sidgen = utils.TS6SIDGenerator(self.irc.serverdata["sidrange"]) self.sidgen = utils.TS6SIDGenerator(self.irc.serverdata["sidrange"])
self.uidgen = {} self.uidgen = {}
# Whether the IRCd allows forcing user mode changes on other servers' clients.
self.allow_forceset_usermodes = True
def spawnClient(self, nick, ident='null', host='null', realhost=None, modes=set(), def spawnClient(self, nick, ident='null', host='null', realhost=None, modes=set(),
server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None): server=None, ip='0.0.0.0', realname=None, ts=None, opertype=None):
"""Spawns a client with nick <nick> on the given IRC connection. """Spawns a client with nick <nick> on the given IRC connection.