diff --git a/classes.py b/classes.py index 69e9bb4..f9d78a3 100644 --- a/classes.py +++ b/classes.py @@ -112,6 +112,9 @@ class User(TSObject): # Stores service bot name if applicable self.service = None + # Whether the user is using SSL/TLS (None = unknown) + self.ssl = None + @property def nick(self): return self._nick diff --git a/protocols/hybrid.py b/protocols/hybrid.py index a9a9eee..591a1da 100644 --- a/protocols/hybrid.py +++ b/protocols/hybrid.py @@ -211,6 +211,9 @@ class HybridProtocol(TS6Protocol): # Call the OPERED UP hook if +o is being added to the mode list. self._check_oper_status_change(uid, parsedmodes) + # Track SSL/TLS status + self.users[uid].ssl = ('+S', None) in parsedmodes + # Set the account name if present if account: self.call_hooks([uid, 'CLIENT_SERVICES_LOGIN', {'text': account}]) diff --git a/protocols/inspircd.py b/protocols/inspircd.py index 5d59e12..0fedfaa 100644 --- a/protocols/inspircd.py +++ b/protocols/inspircd.py @@ -986,6 +986,8 @@ class InspIRCdProtocol(TS6BaseProtocol): self._modsupport.add(module[1:]) else: log.warning('(%s) Got unknown METADATA modules string: %r', self.name, args[-1]) + elif args[1] == 'ssl_cert' and uid in self.users: + self.users[uid].ssl = True def handle_version(self, numeric, command, args): """ diff --git a/protocols/p10.py b/protocols/p10.py index 055fd7e..2e3cfdc 100644 --- a/protocols/p10.py +++ b/protocols/p10.py @@ -935,6 +935,7 @@ class P10Protocol(IRCS2SProtocol): ident, host, realname, realhost, ip) uobj = self.users[uid] = User(self, nick, ts, uid, source, ident, host, realname, realhost, ip) + uobj.ssl = False self.servers[source].users.add(uid) # https://github.com/evilnet/nefarious2/blob/master/doc/p10.txt#L708 @@ -952,6 +953,9 @@ class P10Protocol(IRCS2SProtocol): accountname = modepair[1].split(':', 1)[0] self.call_hooks([uid, 'CLIENT_SERVICES_LOGIN', {'text': accountname}]) + elif modepair[0][-1] == self.umodes.get('ssl'): # track SSL status where available + uobj.ssl = True + # Call the OPERED UP hook if +o is being added to the mode list. self._check_oper_status_change(uid, parsedmodes) diff --git a/protocols/ts6.py b/protocols/ts6.py index 5b434f9..96c3c67 100644 --- a/protocols/ts6.py +++ b/protocols/ts6.py @@ -317,19 +317,19 @@ class TS6Protocol(TS6BaseProtocol): 'quiet': 'q', 'redirect': 'f', 'freetarget': 'F', 'joinflood': 'j', 'largebanlist': 'L', 'permanent': 'P', 'noforwards': 'Q', 'stripcolor': 'c', 'allowinvite': - 'g', 'opmoderated': 'z', 'noctcp': 'C', 'ssl': 'Z', + 'g', 'opmoderated': 'z', 'noctcp': 'C', # charybdis modes provided by extensions 'operonly': 'O', 'adminonly': 'A', 'sslonly': 'S', 'nonotice': 'T', - '*A': 'beIq', '*B': 'k', '*C': 'lfj', '*D': 'mnprstFLPQcgzCZOAST' + '*A': 'beIq', '*B': 'k', '*C': 'lfj', '*D': 'mnprstFLPQcgzCOAST' }) self.umodes.update({ 'deaf': 'D', 'servprotect': 'S', 'admin': 'a', 'invisible': 'i', 'oper': 'o', 'wallops': 'w', 'snomask': 's', 'noforward': 'Q', 'regdeaf': 'R', 'callerid': 'g', 'operwall': 'z', 'locops': 'l', - 'cloak': 'x', 'override': 'p', - '*A': '', '*B': '', '*C': '', '*D': 'DSaiowsQRgzlxp' + 'cloak': 'x', 'override': 'p', 'ssl': 'Z', + '*A': '', '*B': '', '*C': '', '*D': 'DSaiowsQRgzlxpZ' }) # Charybdis extbans @@ -605,6 +605,10 @@ class TS6Protocol(TS6BaseProtocol): if accountname != "*": self.call_hooks([uid, 'CLIENT_SERVICES_LOGIN', {'text': accountname}]) + # charybdis and derivatives have a usermode (+Z) to mark SSL connections + # ratbox doesn't appear to have this + self.users[uid].ssl = ('+%s' % self.umodes.get('ssl'), None) in parsedmodes + return {'uid': uid, 'ts': ts, 'nick': nick, 'realhost': realhost, 'host': host, 'ident': ident, 'ip': ip} def handle_uid(self, numeric, command, args): diff --git a/protocols/unreal.py b/protocols/unreal.py index 252544e..796f3f4 100644 --- a/protocols/unreal.py +++ b/protocols/unreal.py @@ -508,6 +508,9 @@ class UnrealProtocol(TS6BaseProtocol): if ('+r', None) in parsedmodes and accountname.isdigit(): accountname = nick + # Track SSL/TLS status + self.users[uid].ssl = ('+z', None) in parsedmodes + if not accountname.isdigit(): self.call_hooks([uid, 'CLIENT_SERVICES_LOGIN', {'text': accountname}])