def onUse(self, user, data): if "targetuser" not in data: return targets = data["targetuser"] for u in targets: user.sendMessage(irc.RPL_WHOISUSER, u.nickname, u.username, u.hostname, "*", ":{}".format(u.realname)) if "o" in user.mode or user == u: user.sendMessage(irc.RPL_WHOISHOST, u.nickname, ":is connecting from {}@{} {}".format(u.username, u.realhost, u.ip)) chanlist = [] for chan in self.ircd.channels.itervalues(): if u in chan.users: chanlist.append(chan) chandisplay = [] for cdata in chanlist: if user in cdata.users or ("s" not in cdata.mode and "p" not in cdata.mode): statuses = cdata.users[u] if u in cdata.users else "" status = self.ircd.prefixes[statuses[0]][0] if statuses else "" chandisplay.append("{}{}".format(status, cdata.name)) if chandisplay: user.sendMessage(irc.RPL_WHOISCHANNELS, u.nickname, ":{}".format(" ".join(chandisplay))) user.sendMessage(irc.RPL_WHOISSERVER, u.nickname, u.server, ":{}".format(self.ircd.servconfig["server_description"] if u.server == self.ircd.name else self.ircd.servers[u.server].description)) if "accountname" in u.metadata["ext"]: user.sendMessage(irc.RPL_WHOISACCOUNT, u.nickname, u.metadata["ext"]["accountname"], ":is logged in as") if u.socket.secure: user.sendMessage(irc.RPL_WHOISSECURE, u.nickname, ":is using a secure connection") if "certfp" in u.metadata["server"]: user.sendMessage(irc.RPL_WHOISCERTFP, u.nickname, ":has client certificate fingerprint {}".format(u.metadata["server"]["certfp"])) if "o" in u.mode: user.sendMessage(irc.RPL_WHOISOPERATOR, u.nickname, ":is an IRC operator") if "whoisdata" in self.ircd.actions: for action in self.ircd.actions["whoisdata"]: action(user, u) user.sendMessage(irc.RPL_WHOISIDLE, u.nickname, str(epoch(now()) - epoch(u.lastactivity)), str(epoch(u.signon)), ":seconds idle, signon time") user.sendMessage(irc.RPL_ENDOFWHOIS, u.nickname, ":End of /WHOIS list")
def data_serialize(self): expiryTime = epoch(now()) - parse_duration(self.ircd.servconfig["client_whowas_expire"]) remove = [] for nick, data in self.whowasCmd.history.iteritems(): while data and epoch(data[0]["time"]) < expiryTime: data.pop(0) if not data: remove.append(nick) for nick in remove: del self.whowasCmd.history[nick] return [self.whowasCmd.history._data, {}]
def onUse(self, user, data): if "reason" in data: self.exceptList[data["mask"]] = { "setter": user.nickname, "created": epoch(now()), "duration": data["duration"], "reason": data["reason"], } user.sendMessage( "NOTICE", ":*** E:Line set on {}, to expire in {} seconds".format(data["mask"], data["duration"]) ) else: mask = data["mask"] del self.exceptList[mask] user.sendMessage("NOTICE", ":*** E:Line removed on {}".format(mask)) for u in self.ircd.users.itervalues(): if self.match_eline(u): u.cache["except_line"] = True now_banned = {} for uid, udata in self.ircd.users.iteritems(): for modfunc in self.ircd.actions["xline_rematch"]: reason = modfunc(udata) if reason: now_banned[uid] = reason break # If the user is banned, the user is banned. We don't need to gather a consensus or something. for uid, reason in now_banned.iteritems(): udata = self.ircd.users[uid] udata.sendMessage("NOTICE", ":{}".format(self.ircd.servconfig["client_ban_msg"])) udata.disconnect("Banned: Exception Removed ({})".format(reason))
def expire_qlines(self): current_time = epoch(now()) expired = [] for mask, linedata in self.banList.iteritems(): if linedata["duration"] and current_time > linedata["created"] + linedata["duration"]: expired.append(mask) for mask in expired: del self.banList[mask]
def expire_glines(self): current_time = epoch(now()) expired = [] for mask, linedata in self.banList.iteritems(): if linedata["duration"] and current_time > linedata["created"] + linedata["duration"]: expired.append(mask) for mask in expired: del self.banList[mask]
def delMetadata(self, namespace, key, sourceServer = None): oldValue = self.metadata[namespace][key] del self.metadata[namespace][key] for modfunc in self.ircd.actions["metadataupdate"]: modfunc(self, namespace, key, oldValue, "") if self.registered == 0: for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name and server.name != sourceServer: server.callRemote(SetMetadata, target=self.uuid, targetts=epoch(self.signon), namespace=namespace, key=key, value="")
def setMetadata(self, namespace, key, value, sourceServer = None): oldValue = self.metadata[namespace][key] if key in self.metadata[namespace] else "" self.metadata[namespace][key] = value for modfunc in self.ircd.actions["metadataupdate"]: modfunc(self, namespace, key, oldValue, value) from txircd.server import SetMetadata # This import is moved to here to alleviate issues with circular dependencies for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name and server.name != sourceServer: server.callRemote(SetMetadata, target=self.name, targetts=epoch(self.created), namespace=namespace, key=key, value=value)
def delMetadata(self, namespace, key, sourceServer = None): oldValue = self.metadata[namespace][key] del self.metadata[namespace][key] for modfunc in self.ircd.actions["metadataupdate"]: modfunc(self, namespace, key, oldValue, "") from txircd.server import SetMetadata for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name and server.name != sourceServer: server.callRemote(SetMetadata, target=self.name, targetts=epoch(self.created), namespace=namespace, key=key, value="")
def sendWhoLine(self, user, targetUser, destination, channel, filters, fields): displayChannel = destination if not channel: for chan in self.ircd.channels.itervalues(): if user in chan.users and targetUser in chan.users: displayChannel = chan break else: displayChannel = "*" udata = { "dest": destination, "nick": targetUser.nickname, "ident": targetUser.username, "host": targetUser.hostname, "ip": targetUser.ip, "server": targetUser.server, "away": "away" in targetUser.metadata["ext"], "oper": "o" in targetUser.mode, "idle": epoch(now()) - epoch(targetUser.lastactivity), "status": self.ircd.prefixes[channel.users[targetUser][0]][0] if channel and channel.users[targetUser] else "", "hopcount": 0, "gecos": targetUser.realname, "account": targetUser.metadata["ext"]["accountname"] if "accountname" in targetUser.metadata["ext"] else "0", "channel": displayChannel } if "wholinemodify" in self.ircd.actions: tryagain = [] for action in self.ircd.actions["wholinemodify"]: newdata = action(user, targetUser, filters, fields, channel, udata) if newdata == "again": tryagain.append(action) elif not newdata: return udata = newdata for action in tryagain: udata = action(user, targetUser, filters, fields, channel, udata) if not udata: return if "wholinedisplay" in self.ircd.actions: for action in self.ircd.actions["wholinedisplay"]: handled = action(user, targetUser, filters, fields, channel, udata) if handled: return user.sendMessage(irc.RPL_WHOREPLY, udata["dest"], udata["ident"], udata["host"], udata["server"], udata["nick"], "{}{}{}".format("G" if udata["away"] else "H", "*" if udata["oper"] else "", udata["status"]), ":{} {}".format(udata["hopcount"], udata["gecos"]))
def addToWhowas(self, user, reason): if user.registered > 0: return # don't process users who haven't yet registered newEntry = { "nick": user.nickname, "ident": user.username, "host": user.hostname, "gecos": user.realname, "server": user.server, "time": now() } if user.nickname in self.history: self.history[user.nickname].append(newEntry) self.history[user.nickname] = self.history[user.nickname][-self.ircd.servconfig["client_whowas_limit"]:] expiryTime = epoch(now()) - parse_duration(self.ircd.servconfig["client_whowas_expire"]) while epoch(self.history[user.nickname][0]["time"]) < expiryTime: self.history[user.nickname].pop(0) else: self.history[user.nickname] = [newEntry]
def showParam(self, user, target): if "s" in target.mode: for mask in target.mode["s"]: time = target.cache["servernoticedata"][ mask] if "servernoticedata" in target.cache and mask in target.cache[ "servernoticedata"] else epoch(now()) user.sendMessage(irc.RPL_LISTMODE, target.nickname, "s", mask, target.nickname, str(time)) user.sendMessage(irc.RPL_ENDOFLISTMODE, target.nickname, "s", ":End of server notice type list")
def setTopic(self, topic, setter): for action in self.ircd.actions["topic"]: action(self, topic, setter) self.topic = str(topic) self.topicSetter = str(setter) self.topicTime = now() from txircd.server import SetTopic for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote(SetTopic, channel=self.name, chants=epoch(self.created), topic=topic, topicsetter=setter, topicts=epoch(self.topicTime))
def irc_NICK(self, prefix, params): if not params: self.sendMessage(irc.ERR_NONICKNAMEGIVEN, ":No nickname given", prefix=self.factory.server_name) elif not VALID_USERNAME.match(params[0]): self.sendMessage( irc.ERR_ERRONEUSNICKNAME, params[0], ":Erroneous nickname", prefix=self.factory.server_name ) elif params[0] in self.factory.users: self.sendMessage( irc.ERR_NICKNAMEINUSE, self.factory.users[params[0]].nickname, ":Nickname is already in use", prefix=self.factory.server_name, ) else: lower_nick = irc_lower(params[0]) expired = [] for mask, linedata in self.factory.xlines["Q"].iteritems(): if linedata["duration"] != 0 and epoch(now()) > epoch(linedata["created"]) + linedata["duration"]: expired.append(mask) continue if fnmatch.fnmatch(lower_nick, mask): self.sendMessage( irc.ERR_ERRONEUSNICKNAME, self.nick if self.nick else "*", params[0], ":Invalid nickname: {}".format(linedata["reason"]), prefix=self.factory.server_name, ) return for mask in expired: del self.factory.xlines["Q"][mask] if expired: self.factory.save_options() self.nick = params[0] if self.user: try: self.type = self.factory.types["user"](self, self.user, self.password, self.nick) except ValueError: self.type = None self.transport.loseConnection()
def connectionMade(self): self.secure = ISSLTransport(self.transport, None) is not None self.data_checker.start(5) self.last_message = now() self.pinger.start(self.factory.client_ping_interval) ip = self.transport.getPeer().host expired = [] for mask, linedata in self.factory.xlines["Z"].iteritems(): if linedata["duration"] != 0 and epoch(now()) > epoch(linedata["created"]) + linedata["duration"]: expired.append(mask) continue if fnmatch.fnmatch(ip, mask): self.sendMessage( "NOTICE", "*", ":{}".format(self.factory.client_ban_msg), prefix=self.factory.server_name ) self.sendMessage("ERROR", ":Closing Link {} [Z:Lined: {}]".format(ip, linedata["reason"])) self.transport.loseConnection() for mask in expired: del self.factory.xlines["Z"][mask] if expired: self.factory.save_options()
def checkSet(self, user, target, param): if "o" not in user.mode: user.sendMessage(irc.ERR_NOPRIVILEGES, ":Permission denied - Only operators may set user mode s") return [False, param] mask = irc_lower(param) if mask not in self.tellLists: self.tellLists[mask] = [] self.tellLists[mask].append(target) if "servernoticedata" not in target.cache: target.cache["servernoticedata"] = {} target.cache["servernoticedata"][mask] = epoch(now()) return [True, mask]
def statsChars(self, user, statschar): if statschar == "o": for user in self.ircd.users.itervalues(): if "o" in user.mode: user.sendMessage( irc.RPL_STATSOPERS, ":{} ({}@{}) Idle: {} secs".format( user.nickname, user.username, user.hostname, epoch(now()) - epoch(user.lastactivity))) elif statschar == "p": for port in self.ircd.client_ports.iterkeys(): user.sendMessage(irc.RPL_STATSPORTS, ":{} (clients)".format(port)) for port in self.ircd.server_ports.iterkeys(): user.sendMessage(irc.RPL_STATSPORTS, ":{} (servers)".format(port)) elif statschar == "u": uptime = now() - self.ircd.created user.sendMessage( irc.RPL_STATSUPTIME, ":Server up {}".format(uptime if uptime.days > 0 else "0 days, {}".format(uptime)))
def addToWhowas(self, user, reason): if user.registered > 0: return # don't process users who haven't yet registered newEntry = { "nick": user.nickname, "ident": user.username, "host": user.hostname, "realhost": user.realhost, "ip": user.ip, "gecos": user.realname, "server": user.server, "time": now() } if user.nickname in self.history: self.history[user.nickname].append(newEntry) self.history[user.nickname] = self.history[user.nickname][-self.ircd.servconfig["client_whowas_limit"]:] expiryTime = epoch(now()) - parse_duration(self.ircd.servconfig["client_whowas_expire"]) while epoch(self.history[user.nickname][0]["time"]) < expiryTime: self.history[user.nickname].pop(0) else: self.history[user.nickname] = [newEntry]
def setMetadata(self, namespace, key, value, sourceServer = None): key = str(key) if not value: self.delMetadata(namespace, key, sourceServer) return value = str(value) oldValue = self.metadata[namespace][key] if key in self.metadata[namespace] else "" self.metadata[namespace][key] = value for modfunc in self.ircd.actions["metadataupdate"]: modfunc(self, namespace, key, oldValue, value) if self.registered == 0: for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name and server.name != sourceServer: server.callRemote(SetMetadata, target=self.uuid, targetts=epoch(self.signon), namespace=namespace, key=key, value=value)
def checkSet(self, user, target, param): if "o" not in user.mode: user.sendMessage( irc.ERR_NOPRIVILEGES, ":Permission denied - Only operators may set user mode s") return [False, param] mask = irc_lower(param) if mask not in self.tellLists: self.tellLists[mask] = [] self.tellLists[mask].append(target) if "servernoticedata" not in target.cache: target.cache["servernoticedata"] = {} target.cache["servernoticedata"][mask] = epoch(now()) return [True, mask]
def join(self, channel): if self in channel.users: return status = "" for server in self.ircd.servers.itervalues(): # Send this first before the chancreate hook screws up everything if server.nearHop == self.ircd.name: server.callRemote(JoinChannel, channel=channel.name, chants=epoch(channel.created), user=self.uuid) if channel.name not in self.ircd.channels: self.ircd.channels[channel.name] = channel for modfunc in self.ircd.actions["chancreate"]: modfunc(channel) status = self.ircd.servconfig["channel_default_status"] channel.users[self] = status joinShowUsers = channel.users.keys() tryagain = [] for modfunc in self.ircd.actions["joinmessage"]: result = modfunc(channel, self, joinShowUsers) if result == "again": tryagain.append(modfunc) else: joinShowUsers = result for modfunc in tryagain: joinShowUsers = modfunc(channel, self, joinShowUsers) for u in joinShowUsers: u.sendMessage("JOIN", to=channel.name, prefix=self.prefix()) if channel.topic: self.sendMessage(irc.RPL_TOPIC, channel.name, ":{}".format(channel.topic)) self.sendMessage(irc.RPL_TOPICWHOTIME, channel.name, channel.topicSetter, str(epoch(channel.topicTime))) else: self.sendMessage(irc.RPL_NOTOPIC, channel.name, ":No topic is set") self.report_names(channel) if status: for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote(SetMode, target=channel.name, targetts=epoch(channel.created), source=self.ircd.name, modestring="+{}".format(status), params=[self.nickname for i in range(len(status))]) for modfunc in self.ircd.actions["join"]: modfunc(self, channel)
def checkSet(self, user, target, param): if " " in param: param = param[:param.index(" ")] if "b" in target.mode and len(target.mode["b"]) >= self.ircd.servconfig["channel_ban_list_size"]: return [False, param] if "!" not in param and "@" not in param: param = "{}!*@*".format(param) elif "@" not in param: param = "{}@*".format(param) elif "!" not in param: param = "*!{}".format(param) if "bandata" not in target.cache: target.cache["bandata"] = {} target.cache["bandata"][param] = [user.nickname, epoch(now())] return [True, param]
def delMetadata(self, namespace, key, sourceServer=None): key = str(key) oldValue = self.metadata[namespace][key] del self.metadata[namespace][key] for modfunc in self.ircd.actions["metadataupdate"]: modfunc(self, namespace, key, oldValue, "") from txircd.server import SetMetadata for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name and server.name != sourceServer: server.callRemote(SetMetadata, target=self.name, targetts=epoch(self.created), namespace=namespace, key=key, value="")
def delMetadata(self, namespace, key, sourceServer=None): key = str(key) oldValue = self.metadata[namespace][key] del self.metadata[namespace][key] for modfunc in self.ircd.actions["metadataupdate"]: modfunc(self, namespace, key, oldValue, "") if self.registered == 0: for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name and server.name != sourceServer: server.callRemote(SetMetadata, target=self.uuid, targetts=epoch(self.signon), namespace=namespace, key=key, value="")
def onUse(self, user, data): if "targetchan" in data: if "modes" in data: data["targetchan"].setMode(user, data["modes"], data["params"]) else: channel = data["targetchan"] user.sendMessage(irc.RPL_CHANNELMODEIS, channel.name, channel.modeString(user)) user.sendMessage(irc.RPL_CREATIONTIME, channel.name, str(epoch(channel.created))) elif "targetuser" in data: if user == data["targetuser"]: if "modes" in data: data["targetuser"].setMode(user, data["modes"], data["params"]) else: user.sendMessage(irc.RPL_UMODEIS, user.modeString(user)) else: user.sendMessage(irc.ERR_USERSDONTMATCH, ":Can't operate on modes for other users")
def onUse(self, user, data): if "reason" in data: self.shunList[data["mask"]] = { "setter": user.nickname, "created": epoch(now()), "duration": data["duration"], "reason": data["reason"] } user.sendMessage("NOTICE", ":*** Shun set on {}, to expire in {} seconds".format(data["mask"], data["duration"])) else: del self.shunList[data["mask"]] user.sendMessage("NOTICE", ":*** Shun removed on {}".format(data["mask"])) for udata in self.ircd.users.itervalues(): if self.match_shun(udata): udata.cache["shunned"] = True else: udata.cache["shunned"] = False
def onUse(self, user, data): cdata = data["targetchan"] if "topic" not in data: if cdata.topic: user.sendMessage(irc.RPL_TOPIC, cdata.name, ":{}".format(cdata.topic)) user.sendMessage(irc.RPL_TOPICWHOTIME, cdata.name, cdata.topicSetter, str(epoch(cdata.topicTime))) else: user.sendMessage(irc.RPL_NOTOPIC, cdata.name, "No topic is set") else: cdata.setTopic(data["topic"], user.prefix()) cdata.sendChannelMessage("TOPIC", ":{}".format(cdata.topic), prefix=user.prefix())
def setMetadata(self, namespace, key, value, sourceServer=None): key = str(key) if not value: self.delMetadata(namespace, key, sourceServer) return value = str(value) oldValue = self.metadata[namespace][key] if key in self.metadata[ namespace] else "" self.metadata[namespace][key] = value for modfunc in self.ircd.actions["metadataupdate"]: modfunc(self, namespace, key, oldValue, value) from txircd.server import SetMetadata # This import is moved to here to alleviate issues with circular dependencies for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name and server.name != sourceServer: server.callRemote(SetMetadata, target=self.name, targetts=epoch(self.created), namespace=namespace, key=key, value=value)
def onUse(self, user, data): if "reason" in data: self.shunList[data["mask"]] = { "setter": user.nickname, "created": epoch(now()), "duration": data["duration"], "reason": data["reason"] } user.sendMessage( "NOTICE", ":*** Shun set on {}, to expire in {} seconds".format( data["mask"], data["duration"])) else: del self.shunList[data["mask"]] user.sendMessage("NOTICE", ":*** Shun removed on {}".format(data["mask"])) for udata in self.ircd.users.itervalues(): if self.match_shun(udata): udata.cache["shunned"] = True else: udata.cache["shunned"] = False
def onUse(self, user, data): if "reason" in data: self.banList[data["mask"]] = { "setter": user.nickname, "created": epoch(now()), "duration": data["duration"], "reason": data["reason"] } user.sendMessage("NOTICE", ":*** Z:Line set on {}, to expire in {} seconds".format(data["mask"], data["duration"])) now_banned = {} for uid, udata in self.ircd.users.iteritems(): reason = self.match_zline(udata) if reason: now_banned[uid] = reason for uid, reason in now_banned.iteritems(): udata = self.ircd.users[uid] udata.sendMessage("NOTICE", ":{}".format(self.ircd.servconfig["client_ban_msg"])) udata.disconnect("Z:Lined: {}".format(reason)) else: del self.banList[data["mask"]] user.sendMessage("NOTICE", ":*** Z:Line removed on {}".format(data["mask"]))
def onUse(self, user, data): if "reason" in data: self.banList[data["mask"]] = { "setter": user.prefix(), "created": epoch(now()), "duration": data["duration"], "reason": data["reason"] } user.sendMessage("NOTICE", ":*** K:Line added on {}, to expire in {} seconds".format(data["mask"], data["duration"])) now_banned = {} for nick, u in self.ircd.users.iteritems(): if u.server == self.ircd.name: result = self.match_kline(u) if result: now_banned[nick] = result for uid, reason in now_banned.iteritems(): udata = self.ircd.users[uid] udata.sendMessage("NOTICE", ":{}".format(self.ircd.servconfig["client_ban_msg"])) udata.disconnect("K:Lined: {}".format(reason)) else: del self.banList[data["mask"]] user.sendMessage("NOTICE", ":*** K:Line removed on {}".format(data["mask"]))
def onUse(self, user, data): mask = data["mask"] if "reason" in data: self.banList[mask] = { "setter": user.nickname, "created": epoch(now()), "duration": data["duration"], "reason": data["reason"] } user.sendMessage("NOTICE", ":*** Q:Line set on {}, to expire in {} seconds".format(mask, data["duration"])) if "*" not in mask and "?" not in mask: if mask in self.ircd.users: self.ircd.users[mask].disconnect("Q:Lined: {}".format(data["reason"])) else: now_banned = {} for user in self.ircd.users.itervalues(): reason = self.match_qline(user) if reason: now_banned[user] = reason for user, reason in now_banned.iteritems(): user.disconnect("Q:Lined: {}".format(reason)) else: del self.banList[mask] user.sendMessage("NOTICE", ":*** Q:Line removed on {}".format(mask))
def statsChars(self, cmd, data): if cmd != "STATS": return caller = data["user"] statschar = data["statstype"] if statschar == "o": for user in self.ircd.users.itervalues(): if "o" in user.mode: caller.sendMessage(irc.RPL_STATSOPERS, ":{} ({}@{}) Idle: {} secs".format(user.nickname, user.username, user.hostname, epoch(now()) - epoch(user.lastactivity))) elif statschar == "p": if isinstance(self.ircd.servconfig["server_port_tcp"], collections.Sequence): for port in self.ircd.servconfig["server_port_tcp"]: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (clients, plaintext)".format(port)) else: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (clients, plaintext)".format(self.ircd.servconfig["server_port_tcp"])) if isinstance(self.ircd.servconfig["server_port_ssl"], collections.Sequence): for port in self.ircd.servconfig["server_port_ssl"]: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (clients, ssl)".format(port)) else: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (clients, ssl)".format(self.ircd.servconfig["server_port_ssl"])) if isinstance(self.ircd.servconfig["server_port_web"], collections.Sequence): for port in self.ircd.servconfig["server_port_web"]: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (clients, web)".format(port)) else: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (clients, web)".format(self.ircd.servconfig["server_port_web"])) if isinstance(self.ircd.servconfig["serverlink_port_tcp"], collections.Sequence): for port in self.ircd.servconfig["serverlink_port_tcp"]: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (servers, plaintext)".format(port)) else: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (servers, plaintext)".format(self.ircd.servconfig["serverlink_port_tcp"])) if isinstance(self.ircd.servconfig["serverlink_port_ssl"], collections.Sequence): for port in self.ircd.servconfig["serverlink_port_ssl"]: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (servers, ssl)".format(port)) else: caller.sendMessage(irc.RPL_STATSPORTS, ":{} (servers, ssl)".format(self.ircd.servconfig["serverlink_port_ssl"])) elif statschar == "u": uptime = now() - self.ircd.created caller.sendMessage(irc.RPL_STATSUPTIME, ":Server up {}".format(uptime if uptime.days > 0 else "0 days, {}".format(uptime)))
def connectionMade(self): self.connection_expire.cancel() self.type = IRCUser(self) tryagain = [] for function in self.factory.actions["connect"]: result = function(self.type) if result == "again": tryagain.append(function) elif not result: self.transport.loseConnection() self.type = None break if self.type: for function in tryagain: if not function(self.type): self.transport.loseConnection() self.type = None break if self.type: self.secure = ISSLTransport(self.transport, None) is not None self.data_checker.start(5) self.pinger.start(self.factory.servconfig["client_ping_interval"], now=False) for server in self.factory.servers.itervalues(): if server.nearHop == self.factory.name: server.callRemote(ConnectUser, uuid=self.type.uuid, ip=self.type.ip, server=self.factory.name, secure=self.secure, signon=epoch(self.type.signon))
def showParam(self, user, target): if "b" in target.mode: for entry in target.mode["b"]: metadata = target.cache["bandata"][entry] if "bandata" in target.cache and entry in target.cache["bandata"] else [ self.ircd.name, epoch(now()) ] user.sendMessage(irc.RPL_BANLIST, target.name, entry, metadata[0], str(metadata[1])) if "bandata" in target.cache: removeMask = [] for mask in target.cache["bandata"]: if mask not in target.mode["b"]: removeMask.append(mask) for mask in removeMask: del target.cache["bandata"][mask] elif "bandata" in target.cache: del target.cache["bandata"] # clear all saved ban data if no bans are set on channel user.sendMessage(irc.RPL_ENDOFBANLIST, target.name, ":End of channel ban list")
def statsChars(self, user, statschar): if statschar == "o": for user in self.ircd.users.itervalues(): if "o" in user.mode: user.sendMessage(irc.RPL_STATSOPERS, ":{} ({}@{}) Idle: {} secs".format(user.nickname, user.username, user.hostname, epoch(now()) - epoch(user.lastactivity))) elif statschar == "p": for port in self.ircd.client_ports.iterkeys(): user.sendMessage(irc.RPL_STATSPORTS, ":{} (clients)".format(port)) for port in self.ircd.server_ports.iterkeys(): user.sendMessage(irc.RPL_STATSPORTS, ":{} (servers)".format(port)) elif statschar == "u": uptime = now() - self.ircd.created user.sendMessage(irc.RPL_STATSUPTIME, ":Server up {}".format(uptime if uptime.days > 0 else "0 days, {}".format(uptime)))
def register(self): if self.nickname in self.ircd.users: return tryagain = [] for action in self.ircd.actions["register"]: outCode = action(self) if outCode == "again": tryagain.append(action) elif not outCode: log.msg("The new user {} was prevented from connecting by a module.".format(self.nickname)) return self.disconnect(None) for action in tryagain: if not action(self): log.msg("The new user {} was prevented from connecting by a module.".format(self.nickname)) return self.disconnect(None) # Add self to user list self.ircd.users[self.nickname] = self # Send notification of connection to other servers for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote(RegisterUser, uuid=self.uuid, nick=self.nickname, ident=self.username, host=self.hostname, realhost=self.realhost, gecos=self.realname, ip=self.ip, password=self.password if self.password else "", server=self.server, secure=self.socket.secure, signon=epoch(self.signon), nickts=epoch(self.nicktime)) # Send all those lovely join messages chanmodelist = "".join("".join(["".join(modedict.keys()) for modedict in self.ircd.channel_modes]) + "".join(self.ircd.prefixes.keys())) usermodelist = "".join(["".join(modedict.keys()) for modedict in self.ircd.user_modes]) self.sendMessage(irc.RPL_WELCOME, ":Welcome to the Internet Relay Network {}".format(self.prefix())) self.sendMessage(irc.RPL_YOURHOST, ":Your host is {}, running version {}".format(self.ircd.servconfig["server_network_name"], self.ircd.version)) self.sendMessage(irc.RPL_CREATED, ":This server was created {}".format(self.ircd.created)) self.sendMessage(irc.RPL_MYINFO, self.ircd.servconfig["server_network_name"], self.ircd.version, usermodelist, chanmodelist) # usermodes & channel modes self.send_isupport() self.send_lusers() self.send_motd() for action in self.ircd.actions["welcome"]: action(self)
def setMode(self, user, modes, params, displayPrefix = None): adding = True currentParam = 0 modeDisplay = [] for mode in modes: if mode == "+": adding = True elif mode == "-": adding = False else: if mode not in self.ircd.user_mode_type: if user: user.sendMessage(irc.ERR_UMODEUNKNOWNFLAG, mode, ":is unknown mode char to me") continue modetype = self.ircd.user_mode_type[mode] if modetype == 1 or (adding and modetype == 2) or (modetype == 0 and len(params) > currentParam): if len(params) <= currentParam: continue # mode must have parameter, but one wasn't provided param = params[currentParam] currentParam += 1 if " " in param: param = param[:param.find(" ")] else: param = None if not (modetype == 0 and param is None): # ignore these checks for list modes so that they can be listed if not adding and mode not in self.mode: continue # cannot unset a mode that's not set if user: if adding: allowed, param = self.ircd.user_modes[modetype][mode].checkSet(user, self, param) if not allowed: continue else: allowed, param = self.ircd.user_modes[modetype][mode].checkUnset(user, self, param) if not allowed: continue if modetype == 0: if not param and user: self.ircd.user_modes[modetype][mode].showParam(user, self) elif adding: if mode not in self.mode: self.mode[mode] = [] if param not in self.mode[mode]: self.mode[mode].append(param) modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if param in self.mode[mode]: self.mode[mode].remove(param) modeDisplay.append([adding, mode, param]) if not self.mode[mode]: del self.mode[mode] else: if adding: if mode in self.mode and param == self.mode[mode]: continue self.mode[mode] = param modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if modetype == 1 and param != self.mode[mode]: continue del self.mode[mode] modeDisplay.append([adding, mode, param]) if modeDisplay: adding = None modestring = [] showParams = [] for mode in modeDisplay: if mode[0] and adding != "+": adding = "+" modestring.append("+") elif not mode[0] and adding != "-": adding = "-" modestring.append("-") modestring.append(mode[1]) if mode[2]: showParams.append(mode[2]) modeLine = "{} {}".format("".join(modestring), " ".join(showParams)) if showParams else "".join(modestring) if user: self.sendMessage("MODE", modeLine, prefix=user.prefix()) lineSource = user.prefix() elif displayPrefix: self.sendMessage("MODE", modeLine, prefix=displayPrefix) lineSource = displayPrefix else: # display from this server self.sendMessage("MODE", modeLine) lineSource = self.ircd.name for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote(SetMode, target=self.uuid, targetts=epoch(self.signon), source=lineSource, modestring="".join(modestring), params=showParams) for action in self.ircd.actions["mode"]: action(self, lineSource, modeLine, modeDisplay) return modeLine return ""
def sendWhoLine(self, user, targetUser, destination, channel, filters, fields): displayChannel = destination if not channel: for chan in self.ircd.channels.itervalues(): if user in chan.users and targetUser in chan.users: displayChannel = chan break else: displayChannel = "*" udata = { "dest": destination, "nick": targetUser.nickname, "ident": targetUser.username, "host": targetUser.hostname, "ip": targetUser.ip, "server": targetUser.server, "away": "away" in targetUser.metadata["ext"], "oper": "o" in targetUser.mode, "idle": epoch(now()) - epoch(targetUser.lastactivity), "status": self.ircd.prefixes[channel.users[targetUser][0]][0] if channel and channel.users[targetUser] else "", "hopcount": 0, "gecos": targetUser.realname, "account": targetUser.metadata["ext"]["accountname"] if "accountname" in targetUser.metadata["ext"] else "0", "channel": displayChannel } if "wholinemodify" in self.ircd.actions: tryagain = [] for action in self.ircd.actions["wholinemodify"]: newdata = action(user, targetUser, filters, fields, channel, udata) if newdata == "again": tryagain.append(action) elif not newdata: return udata = newdata for action in tryagain: udata = action(user, targetUser, filters, fields, channel, udata) if not udata: return if "wholinedisplay" in self.ircd.actions: for action in self.ircd.actions["wholinedisplay"]: handled = action(user, targetUser, filters, fields, channel, udata) if handled: return user.sendMessage( irc.RPL_WHOREPLY, udata["dest"], udata["ident"], udata["host"], udata["server"], udata["nick"], "{}{}{}".format("G" if udata["away"] else "H", "*" if udata["oper"] else "", udata["status"]), ":{} {}".format(udata["hopcount"], udata["gecos"]))
def setMode(self, user, modes, params, displayPrefix=None): adding = True currentParam = 0 modeDisplay = [] for mode in modes: if mode == "+": adding = True elif mode == "-": adding = False else: if mode not in self.ircd.user_mode_type: if user: user.sendMessage(irc.ERR_UMODEUNKNOWNFLAG, mode, ":is unknown mode char to me") continue modetype = self.ircd.user_mode_type[mode] if modetype == 1 or (adding and modetype == 2) or ( modetype == 0 and len(params) > currentParam): if len(params) <= currentParam: continue # mode must have parameter, but one wasn't provided param = params[currentParam] currentParam += 1 if " " in param: param = param[:param.find(" ")] else: param = None if not ( modetype == 0 and param is None ): # ignore these checks for list modes so that they can be listed if not adding and mode not in self.mode: continue # cannot unset a mode that's not set if user: if adding: allowed, param = self.ircd.user_modes[modetype][ mode].checkSet(user, self, param) if not allowed: continue else: allowed, param = self.ircd.user_modes[modetype][ mode].checkUnset(user, self, param) if not allowed: continue if modetype == 0: if not param and user: self.ircd.user_modes[modetype][mode].showParam( user, self) elif adding: if mode not in self.mode: self.mode[mode] = [] if param not in self.mode[mode]: self.mode[mode].append(param) modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if param in self.mode[mode]: self.mode[mode].remove(param) modeDisplay.append([adding, mode, param]) if not self.mode[mode]: del self.mode[mode] else: if adding: if mode in self.mode and param == self.mode[mode]: continue self.mode[mode] = param modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if modetype == 1 and param != self.mode[mode]: continue del self.mode[mode] modeDisplay.append([adding, mode, param]) if modeDisplay: adding = None modestring = [] showParams = [] for mode in modeDisplay: if mode[0] and adding != "+": adding = "+" modestring.append("+") elif not mode[0] and adding != "-": adding = "-" modestring.append("-") modestring.append(mode[1]) if mode[2]: showParams.append(mode[2]) modeLine = "{} {}".format( "".join(modestring), " ".join(showParams)) if showParams else "".join(modestring) if user: self.sendMessage("MODE", modeLine, prefix=user.prefix()) lineSource = user.prefix() elif displayPrefix: self.sendMessage("MODE", modeLine, prefix=displayPrefix) lineSource = displayPrefix else: # display from this server self.sendMessage("MODE", modeLine) lineSource = self.ircd.name for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote(SetMode, target=self.uuid, targetts=epoch(self.signon), source=lineSource, modestring="".join(modestring), params=showParams) for action in self.ircd.actions["mode"]: action(self, lineSource, modeLine, modeDisplay) return modeLine return ""
def setMode(self, user, modes, params, displayPrefix=None): adding = True currentParam = 0 modeDisplay = [] for mode in modes: if mode == "+": adding = True elif mode == "-": adding = False else: if mode not in self.ircd.channel_mode_type: if user: user.sendMessage(irc.ERR_UNKNOWNMODE, mode, ":is unknown mode char to me") continue modetype = self.ircd.channel_mode_type[mode] if modetype == -1 or ( modetype == 0 and len(params) > currentParam ) or modetype == 1 or (adding and modetype == 2): if len(params) <= currentParam: continue # The mode must have a parameter, but one wasn't provided param = str( params[currentParam] ) # Prevent similar-to-str types that aren't str (like unicode) which breaks things when sent currentParam += 1 if " " in param: param = param[:param.find(" ")] else: param = None if not ( modetype == 0 and param is None ): # ignore these checks for list modes so that they can be listed if not adding and modetype >= 0 and mode not in self.mode: continue # The channel does not have the mode set, so we can't remove it if modetype >= 0 and user: if adding: allowed, param = self.ircd.channel_modes[modetype][ mode].checkSet(user, self, param) if not allowed: continue else: allowed, param = self.ircd.channel_modes[modetype][ mode].checkUnset(user, self, param) if not allowed: continue if modetype == -1: if param not in self.ircd.users: continue udata = self.ircd.users[param] if user and user not in self.users: continue if adding and mode in self.users[udata]: continue if not adding and mode not in self.users[udata]: continue if mode in self.ircd.servconfig[ "channel_status_minimum_change"]: minimum_level = self.ircd.servconfig[ "channel_status_minimum_change"][mode] else: minimum_level = mode if not adding and user == udata: minimum_level = mode # Make the user always allowed to unset from self if user and user.hasAccess(self, minimum_level): if adding: allowed, param = self.ircd.prefixes[mode][ 2].checkSet(user, self, param) if not allowed: continue else: allowed, param = self.ircd.prefixes[mode][ 2].checkUnset(user, self, param) if not allowed: continue elif user: user.sendMessage( irc.ERR_CHANOPRIVSNEEDED, self.name, ":You do not have the level required to change mode +{}" .format(mode)) continue if udata not in self.users: continue if adding: status = self.users[udata] statusList = list(status) for index, statusLevel in enumerate(status): if self.ircd.prefixes[statusLevel][ 1] < self.ircd.prefixes[mode][1]: statusList.insert(index, mode) break if mode not in statusList: # no status to put this one before was found, so this goes at the end statusList.append(mode) self.users[udata] = "".join(statusList) modeDisplay.append([adding, mode, param]) else: if mode in self.users[udata]: self.users[udata] = self.users[udata].replace( mode, "") modeDisplay.append([adding, mode, param]) elif modetype == 0: if not param and user: self.ircd.channel_modes[modetype][mode].showParam( user, self) elif adding: if mode not in self.mode: self.mode[mode] = [] if param not in self.mode[mode]: self.mode[mode].append(param) modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if param in self.mode[mode]: self.mode[mode].remove(param) modeDisplay.append([adding, mode, param]) if not self.mode[mode]: del self.mode[mode] else: if adding: if mode in self.mode and param == self.mode[mode]: continue self.mode[mode] = param modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if modetype == 1 and param != self.mode[mode]: continue del self.mode[mode] modeDisplay.append([adding, mode, param]) if modeDisplay: adding = None modestring = [] showParams = [] for mode in modeDisplay: if mode[0] and adding != "+": adding = "+" modestring.append("+") elif not mode[0] and adding != "-": adding = "-" modestring.append("-") modestring.append(mode[1]) if mode[2]: showParams.append(mode[2]) modeLine = "{} {}".format( "".join(modestring), " ".join(showParams)) if showParams else "".join(modestring) if user: for u in self.users.iterkeys(): u.sendMessage("MODE", modeLine, to=self.name, prefix=user.prefix()) lineSource = user.prefix() elif displayPrefix: for u in self.users.iterkeys(): u.sendMessage("MODE", modeLine, to=self.name, prefix=displayPrefix) lineSource = displayPrefix else: for u in self.users.iterkeys(): u.sendMessage("MODE", modeLine, to=self.name) lineSource = self.ircd.name from txircd.server import SetMode for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote(SetMode, target=self.name, targetts=epoch(self.created), source=lineSource, modestring="".join(modestring), params=showParams) for action in self.ircd.actions["mode"]: action(self, lineSource, modeLine, modeDisplay) return modeLine return ""
def register(self): if self.nickname in self.ircd.users: return tryagain = [] for action in self.ircd.actions["register"]: outCode = action(self) if outCode == "again": tryagain.append(action) elif not outCode: log.msg( "The new user {} was prevented from connecting by a module." .format(self.nickname)) return self.disconnect(None) for action in tryagain: if not action(self): log.msg( "The new user {} was prevented from connecting by a module." .format(self.nickname)) return self.disconnect(None) # Add self to user list self.ircd.users[self.nickname] = self # Send notification of connection to other servers for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote( RegisterUser, uuid=self.uuid, nick=self.nickname, ident=self.username, host=self.hostname, realhost=self.realhost, gecos=self.realname, ip=self.ip, password=self.password if self.password else "", server=self.server, secure=self.socket.secure, signon=epoch(self.signon), nickts=epoch(self.nicktime)) # Send all those lovely join messages chanmodelist = "".join("".join( ["".join(modedict.keys()) for modedict in self.ircd.channel_modes]) + "".join(self.ircd.prefixes.keys())) usermodelist = "".join( ["".join(modedict.keys()) for modedict in self.ircd.user_modes]) self.sendMessage( irc.RPL_WELCOME, ":Welcome to the Internet Relay Network {}".format(self.prefix())) self.sendMessage( irc.RPL_YOURHOST, ":Your host is {}, running version {}".format( self.ircd.servconfig["server_network_name"], self.ircd.version)) self.sendMessage( irc.RPL_CREATED, ":This server was created {}".format(self.ircd.created)) self.sendMessage(irc.RPL_MYINFO, self.ircd.servconfig["server_network_name"], self.ircd.version, usermodelist, chanmodelist) # usermodes & channel modes self.send_isupport() self.send_lusers() self.send_motd() for action in self.ircd.actions["welcome"]: action(self)
def showParam(self, user, target): if "s" in target.mode: for mask in target.mode["s"]: time = target.cache["servernoticedata"][mask] if "servernoticedata" in target.cache and mask in target.cache["servernoticedata"] else epoch(now()) user.sendMessage(irc.RPL_LISTMODE, target.nickname, "s", mask, target.nickname, str(time)) user.sendMessage(irc.RPL_ENDOFLISTMODE, target.nickname, "s", ":End of server notice type list")
def setMode(self, user, modes, params, displayPrefix = None): adding = True currentParam = 0 modeDisplay = [] for mode in modes: if mode == "+": adding = True elif mode == "-": adding = False else: if mode not in self.ircd.channel_mode_type: if user: user.sendMessage(irc.ERR_UNKNOWNMODE, mode, ":is unknown mode char to me") continue modetype = self.ircd.channel_mode_type[mode] if modetype == -1 or (modetype == 0 and len(params) > currentParam) or modetype == 1 or (adding and modetype == 2): if len(params) <= currentParam: continue # The mode must have a parameter, but one wasn't provided param = str(params[currentParam]) # Prevent similar-to-str types that aren't str (like unicode) which breaks things when sent currentParam += 1 if " " in param: param = param[:param.find(" ")] else: param = None if not (modetype == 0 and param is None): # ignore these checks for list modes so that they can be listed if not adding and modetype >= 0 and mode not in self.mode: continue # The channel does not have the mode set, so we can't remove it if modetype >= 0 and user: if adding: allowed, param = self.ircd.channel_modes[modetype][mode].checkSet(user, self, param) if not allowed: continue else: allowed, param = self.ircd.channel_modes[modetype][mode].checkUnset(user, self, param) if not allowed: continue if modetype == -1: if param not in self.ircd.users: continue udata = self.ircd.users[param] if user and user not in self.users: continue if adding and mode in self.users[udata]: continue if not adding and mode not in self.users[udata]: continue if mode in self.ircd.servconfig["channel_status_minimum_change"]: minimum_level = self.ircd.servconfig["channel_status_minimum_change"][mode] else: minimum_level = mode if not adding and user == udata: minimum_level = mode # Make the user always allowed to unset from self if user and user.hasAccess(self, minimum_level): if adding: allowed, param = self.ircd.prefixes[mode][2].checkSet(user, self, param) if not allowed: continue else: allowed, param = self.ircd.prefixes[mode][2].checkUnset(user, self, param) if not allowed: continue elif user: user.sendMessage(irc.ERR_CHANOPRIVSNEEDED, self.name, ":You do not have the level required to change mode +{}".format(mode)) continue if udata not in self.users: continue if adding: status = self.users[udata] statusList = list(status) for index, statusLevel in enumerate(status): if self.ircd.prefixes[statusLevel][1] < self.ircd.prefixes[mode][1]: statusList.insert(index, mode) break if mode not in statusList: # no status to put this one before was found, so this goes at the end statusList.append(mode) self.users[udata] = "".join(statusList) modeDisplay.append([adding, mode, param]) else: if mode in self.users[udata]: self.users[udata] = self.users[udata].replace(mode, "") modeDisplay.append([adding, mode, param]) elif modetype == 0: if not param and user: self.ircd.channel_modes[modetype][mode].showParam(user, self) elif adding: if mode not in self.mode: self.mode[mode] = [] if param not in self.mode[mode]: self.mode[mode].append(param) modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if param in self.mode[mode]: self.mode[mode].remove(param) modeDisplay.append([adding, mode, param]) if not self.mode[mode]: del self.mode[mode] else: if adding: if mode in self.mode and param == self.mode[mode]: continue self.mode[mode] = param modeDisplay.append([adding, mode, param]) else: if mode not in self.mode: continue if modetype == 1 and param != self.mode[mode]: continue del self.mode[mode] modeDisplay.append([adding, mode, param]) if modeDisplay: adding = None modestring = [] showParams = [] for mode in modeDisplay: if mode[0] and adding != "+": adding = "+" modestring.append("+") elif not mode[0] and adding != "-": adding = "-" modestring.append("-") modestring.append(mode[1]) if mode[2]: showParams.append(mode[2]) modeLine = "{} {}".format("".join(modestring), " ".join(showParams)) if showParams else "".join(modestring) if user: for u in self.users.iterkeys(): u.sendMessage("MODE", modeLine, to=self.name, prefix=user.prefix()) lineSource = user.prefix() elif displayPrefix: for u in self.users.iterkeys(): u.sendMessage("MODE", modeLine, to=self.name, prefix=displayPrefix) lineSource = displayPrefix else: for u in self.users.iterkeys(): u.sendMessage("MODE", modeLine, to=self.name) lineSource = self.ircd.name from txircd.server import SetMode for server in self.ircd.servers.itervalues(): if server.nearHop == self.ircd.name: server.callRemote(SetMode, target=self.name, targetts=epoch(self.created), source=lineSource, modestring="".join(modestring), params=showParams) for action in self.ircd.actions["mode"]: action(self, lineSource, modeLine, modeDisplay) return modeLine return ""