From 1888f24ef0bfa88941e27797e917c8bc312d5c00 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sun, 20 Nov 2016 12:29:51 -0800 Subject: [PATCH 1/8] Irc: fix matchHost not using realhost properly (cherry picked from commit f9e798cf936a64bbd6d19341f444ad4ce6bcca36) --- classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes.py b/classes.py index bf29c4a..3ec84cd 100644 --- a/classes.py +++ b/classes.py @@ -1018,7 +1018,7 @@ class Irc(): hosts.add(self.getHostmask(target, ip=True)) if realhost: - hosts.add(self.getHostmask(target, ip=True)) + hosts.add(self.getHostmask(target, realhost=True)) else: # We were given a host, use that. hosts = [target] From e4b2ea60ec20fccdfddf3676657d4c1afa341282 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sun, 2 Oct 2016 22:06:46 -0700 Subject: [PATCH 2/8] Irc: demote unknown user errors in parseModes() to DEBUG Some ancient services like Anope 1.8 set SVS2MODE +d on users when they connect, even if the user quits right after. Due to lag we may receive the MODE after the QUIT instead of before. (cherry picked from commit ec4e71c8cfb86105a28e7bc0b63d91dcc8c37a60) --- classes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/classes.py b/classes.py index 3ec84cd..1320ea4 100644 --- a/classes.py +++ b/classes.py @@ -566,7 +566,7 @@ class Irc(): log.debug('(%s) Using self.umodes for this query: %s', self.name, self.umodes) if target not in self.users: - log.warning('(%s) Possible desync! Mode target %s is not in the users index.', self.name, target) + log.debug('(%s) Possible desync! Mode target %s is not in the users index.', self.name, target) return [] # Return an empty mode list supported_modes = self.umodes From 611b07e6bd2cc2e131940c85bdbc403e2b0d9f23 Mon Sep 17 00:00:00 2001 From: James Lu Date: Fri, 9 Dec 2016 21:51:57 -0800 Subject: [PATCH 3/8] networks: update help for 'disconnect' The 'disconnect' command has been changed to disable autoconnect, but this text was never updated. (cherry picked from commit 34ad79744a816e5ac6bf41963954f1e83c352274) --- plugins/networks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/networks.py b/plugins/networks.py index b9b6d9a..919e08b 100644 --- a/plugins/networks.py +++ b/plugins/networks.py @@ -10,8 +10,8 @@ def disconnect(irc, source, args): """ Disconnects the network . When all networks are disconnected, PyLink will automatically exit. - Note: This does not affect the autoreconnect settings of any network, so the network will likely just reconnect unless autoconnect is disabled (see the 'autoconnect' command).""" - irc.checkAuthenticated(source, allowOper=False) + + To reconnect a network disconnected using this command, use REHASH to reload the networks list.""" try: netname = args[0] network = world.networkobjects[netname] From 3a852393bc6ad86dc0d51f8e4b0e0aaa3a4a08ae Mon Sep 17 00:00:00 2001 From: James Lu Date: Sat, 17 Dec 2016 23:03:28 -0800 Subject: [PATCH 4/8] relay: remove _ from hosts on ts6, ratbox --- plugins/relay.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/relay.py b/plugins/relay.py index 3a5d80c..9163f90 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -182,6 +182,10 @@ def normalizeHost(irc, host): if irc.protoname not in ('inspircd', 'ts6', 'clientbot', 'nefarious'): # UnrealIRCd and IRCd-Hybrid don't allow slashes in hostnames host = host.replace('/', '.') + if irc.protoname in ('ts6', 'ratbox'): + # TS6 doesn't allow _ in hosts. + host = host.replace('_', '.') + host = host.replace('\x03', '') # Strip colours host = host.replace('\x02', '') # Strip bold host = host.replace('\x1f', '') # Strip underline From 3339bf0fe6ced40fcdb0fd0ac3f6f488d9de1599 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sat, 17 Dec 2016 23:47:26 -0800 Subject: [PATCH 5/8] relay: rewrite normalizeHost() to whitelist characters instead --- plugins/relay.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/plugins/relay.py b/plugins/relay.py index eab73be..63c0504 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -172,21 +172,14 @@ def normalize_nick(irc, netname, nick, times_tagged=0, uid=''): return nick +ALLOWED_HOST_CHARS = string.ascii_letters + string.digits + '-.:' def normalize_host(irc, host): """Creates a normalized hostname for the given host suitable for introduction to a remote network (as a relay client).""" log.debug('(%s) relay.normalize_host: IRCd=%s, host=%s', irc.name, irc.protoname, host) - if irc.protoname not in ('inspircd', 'ts6', 'clientbot', 'nefarious'): - # UnrealIRCd and IRCd-Hybrid don't allow slashes in hostnames - host = host.replace('/', '.') - host = host.replace('\x03', '') # Strip colours - host = host.replace('\x02', '') # Strip bold - host = host.replace('\x1f', '') # Strip underline - host = host.replace('\x1d', '') # Strip italic - host = host.replace('\x0f', '') # Strip color reset - host = host.replace('\x16', '') # Strip reverse color - # And no, I'm not supporting colours in hosts. Screw your IRCd-breaking patches if you think - # this is cool. -GL + for char in host: + if char not in ALLOWED_HOST_CHARS: + host = host.replace(char, '-') return host[:63] # Limit hosts to 63 chars for best compatibility From 194a62fceac3b3e03d9e4f5844e2b5974577fb76 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sat, 17 Dec 2016 23:46:30 -0800 Subject: [PATCH 6/8] protocols: implement basic nick collision detection in UID handlers Closes #285. Closes #375. --- protocols/hybrid.py | 1 + protocols/inspircd.py | 1 + protocols/ircs2s_common.py | 12 ++++++++++++ protocols/nefarious.py | 1 + protocols/ts6.py | 1 + protocols/unreal.py | 1 + 6 files changed, 17 insertions(+) diff --git a/protocols/hybrid.py b/protocols/hybrid.py index fe19d8a..065c80a 100644 --- a/protocols/hybrid.py +++ b/protocols/hybrid.py @@ -171,6 +171,7 @@ class HybridProtocol(TS6Protocol): """ # <- :0UY UID dan 1 1451041551 +Facdeiklosuw ~ident localhost 127.0.0.1 0UYAAAAAB * :realname nick = args[0] + self.checkCollision(nick) ts, modes, ident, host, ip, uid, account, realname = args[2:10] if account == '*': account = None diff --git a/protocols/inspircd.py b/protocols/inspircd.py index fa53f4a..0eeb004 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -562,6 +562,7 @@ class InspIRCdProtocol(TS6BaseProtocol): """Handles incoming UID commands (user introduction).""" # :70M UID 70MAAAAAB 1429934638 GL 0::1 hidden-7j810p.9mdf.lrek.0000.0000.IP gl 0::1 1429934638 +Wioswx +ACGKNOQXacfgklnoqvx :realname uid, ts, nick, realhost, host, ident, ip = args[0:7] + self.checkCollision(nick) realname = args[-1] self.irc.users[uid] = userobj = IrcUser(nick, ts, uid, ident, host, realname, realhost, ip) diff --git a/protocols/ircs2s_common.py b/protocols/ircs2s_common.py index c0e92ba..c8542fb 100644 --- a/protocols/ircs2s_common.py +++ b/protocols/ircs2s_common.py @@ -7,6 +7,18 @@ from pylinkirc.log import log class IRCS2SProtocol(Protocol): + def checkCollision(self, nick): + """ + Nick collision checker. + """ + uid = self.irc.nickToUid(nick) + # If there is a nick collision, we simply alert plugins. Relay will purposely try to + # lose fights and tag nicks instead, while other plugins can choose how to handle this. + if uid: + log.info('(%s) Nick collision on %s/%s, forwarding this to plugins', self.irc.name, + uid, nick) + self.irc.callHooks([self.irc.sid, 'SAVE', {'target': uid}]) + def handle_kill(self, source, command, args): """Handles incoming KILLs.""" killed = args[0] diff --git a/protocols/nefarious.py b/protocols/nefarious.py index 5e18f9a..235777a 100644 --- a/protocols/nefarious.py +++ b/protocols/nefarious.py @@ -827,6 +827,7 @@ class P10Protocol(IRCS2SProtocol): # <- AB N GL 1 1460673049 ~gl nefarious.midnight.vpn +iw B]AAAB ABAAA :realname nick = args[0] + self.checkCollision(nick) ts, ident, host = args[2:5] realhost = host ip = args[-3] diff --git a/protocols/ts6.py b/protocols/ts6.py index 036c8ef..4f0b2fb 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -499,6 +499,7 @@ class TS6Protocol(TS6BaseProtocol): """Handles incoming EUID commands (user introduction).""" # <- :42X EUID GL 1 1437505322 +ailoswz ~gl 127.0.0.1 127.0.0.1 42XAAAAAB * * :realname nick = args[0] + self.checkCollision(nick) ts, modes, ident, host, ip, uid, realhost, accountname, realname = args[2:11] if realhost == '*': realhost = None diff --git a/protocols/unreal.py b/protocols/unreal.py index a8fb35a..9b670df 100644 --- a/protocols/unreal.py +++ b/protocols/unreal.py @@ -338,6 +338,7 @@ class UnrealProtocol(TS6BaseProtocol): # arguments: nick, hopcount?, ts, ident, real-host, UID, services account (0 if none), modes, # displayed host, cloaked (+x) host, base64-encoded IP, and realname nick = args[0] + self.checkCollision(nick) ts, ident, realhost, uid, accountname, modestring, host = args[2:9] if host == '*': From ef8ec03e4181655061671651ae0fe0c5d4988dc4 Mon Sep 17 00:00:00 2001 From: James Lu Date: Sun, 18 Dec 2016 23:56:47 -0800 Subject: [PATCH 7/8] relay: re-add / in hosts for networks that support it --- plugins/relay.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugins/relay.py b/plugins/relay.py index 63c0504..bb29c7f 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -172,13 +172,18 @@ def normalize_nick(irc, netname, nick, times_tagged=0, uid=''): return nick -ALLOWED_HOST_CHARS = string.ascii_letters + string.digits + '-.:' def normalize_host(irc, host): """Creates a normalized hostname for the given host suitable for introduction to a remote network (as a relay client).""" log.debug('(%s) relay.normalize_host: IRCd=%s, host=%s', irc.name, irc.protoname, host) + + allowed_chars = string.ascii_letters + string.digits + '-.:' + if irc.protoname in ('inspircd', 'ts6', 'clientbot', 'nefarious'): + # UnrealIRCd and IRCd-Hybrid don't allow slashes in hostnames + allowed_chars += '/' + for char in host: - if char not in ALLOWED_HOST_CHARS: + if char not in allowed_chars: host = host.replace(char, '-') return host[:63] # Limit hosts to 63 chars for best compatibility From c09fce344d733296edec4fdfb31f8184cd8793f0 Mon Sep 17 00:00:00 2001 From: James Lu Date: Mon, 19 Dec 2016 00:00:24 -0800 Subject: [PATCH 8/8] relay: whitelist _ on InspIRCd, UnrealIRCd, Nefarious, clientbot --- plugins/relay.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/relay.py b/plugins/relay.py index bb29c7f..f2e09c0 100644 --- a/plugins/relay.py +++ b/plugins/relay.py @@ -182,6 +182,10 @@ def normalize_host(irc, host): # UnrealIRCd and IRCd-Hybrid don't allow slashes in hostnames allowed_chars += '/' + if irc.protoname in ('inspircd', 'clientbot', 'nefarious', 'unreal'): + # The above IRCds allow _ in hostnames, while TS6-like IRCds do not. + allowed_chars += '_' + for char in host: if char not in allowed_chars: host = host.replace(char, '-')