class KlineCommand(Command): def __init__(self): self.banList = CaseInsensitiveDictionary() 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 processParams(self, user, params): if user.registered > 0: user.sendMessage(irc.ERR_NOTREGISTERED, "KLINE", ":You have not registered") return {} if "o" not in user.mode: user.sendMessage( irc.ERR_NOPRIVILEGES, ":Permission denied - You do not have the correct operator privileges" ) return {} if not params: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} banmask = params[0] if banmask in self.ircd.users: banmask = "{}@{}".format(user.username, user.hostname) elif "@" not in banmask: banmask = "*@{}".format(banmask) self.expire_klines() if banmask[0] == "-": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} if banmask not in self.banList: user.sendMessage( "NOTICE", ":*** K:line for {} does not currently exist; check /stats K for a list of active k:lines" .format(banmask)) return {} return {"user": user, "mask": banmask} if len(params) < 3 or not params[2]: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} if banmask[0] == "+": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} if banmask in self.banList: user.sendMessage( "NOTICE", ":*** There's already a k:line set on {}! Check /stats K for a list of active k:lines." .format(banmask)) return {} return { "user": user, "mask": banmask, "duration": parse_duration(params[1]), "reason": " ".join(params[2:]) } def statsList(self, user, statsType): if statsType != "K": return self.expire_klines() for mask, linedata in self.banList.iteritems(): user.sendMessage( irc.RPL_STATSKLINE, ":{} {} {} {} :{}".format(mask, linedata["created"], linedata["duration"], linedata["setter"], linedata["reason"])) def register_check(self, user): result = self.match_kline(user) if not result: if result == None: return True return "again" user.sendMessage("NOTICE", ":{}".format(self.ircd.servconfig["client_ban_msg"])) user.sendMessage("ERROR", ":Closing Link: {} [K:Lined: {}]".format( user.hostname, result), to=None, prefix=None) return False def match_kline(self, user): if "o" in user.mode: return None # don't allow bans to affect opers if user.server != self.ircd.name: return None # only match users on this server if "except_line" not in user.cache: if "kline_match" in user.cache: return user.cache["kline_match"] # Determine whether the user matches self.expire_klines() match_against = irc_lower("{}@{}".format(user.username, user.hostname)) for mask, linedata in self.banList.iteritems(): if fnmatch(match_against, mask): user.cache["kline_match"] = linedata["reason"] return "" match_against = irc_lower("{}@{}".format(user.username, user.ip)) for mask in self.banList.iterkeys( ): # we just removed expired lines if fnmatch(match_against, mask): user.cache["kline_match"] = linedata["reason"] return "" return None else: if user.cache["except_line"]: return None if "kline_match" in user.cache: return user.cache["kline_match"] self.expire_klines() match_against = irc_lower("{}@{}".format(user.username, user.hostname)) for mask, linedata in self.banList.iteritems(): if fnmatch(match_against, mask): return linedata["reason"] match_against = irc_lower("{}@{}".format(user.username, user.ip)) for mask in self.banList.iterkeys( ): # we just removed expired lines if fnmatch(match_against, mask): return linedata["reason"] return None def expire_klines(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]
class ShunCommand(Command): def __init__(self): self.shunList = CaseInsensitiveDictionary() 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 processParams(self, user, params): if user.registered > 0: user.sendMessage(irc.ERR_NOTREGISTERED, "SHUN", ":You have not registered") return {} if "o" not in user.mode: user.sendMessage(irc.ERR_NOPRIVILEGES, ":Permission denied - You do not have the correct operator privileges") return {} if not params: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} banmask = params[0] if banmask in self.ircd.users: udata = self.ircd.users[banmask] banmask = "{}@{}".format(udata.username, udata.hostname) elif "@" not in banmask: banmask = "*@{}".format(banmask) self.expire_shuns() if banmask[0] == "-": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} if banmask not in self.shunList: user.sendMessage("NOTICE", ":*** Shun {} not found; check /stats S for a list of active shuns.".format(banmask)) return {} return { "user": user, "mask": banmask } if len(params) < 3 or not params[2]: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} if banmask[0] == "+": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} if banmask in self.shunList: user.sendMessage("NOTICE", ":*** Shun {} is already set! Check /stats S for a list of active shuns.".format(banmask)) return {} return { "user": user, "mask": banmask, "duration": parse_duration(params[1]), "reason": " ".join(params[2:]) } def statsList(self, user, statsType): if statsType != "S": return self.expire_shuns() for mask, linedata in self.shunList.iteritems(): user.sendMessage(irc.RPL_STATSSHUN, "{} {} {} {} :{}".format(mask, linedata["created"], linedata["duration"], linedata["setter"], linedata["reason"])) def check_register(self, user): reason = self.match_shun(user) if reason: user.cache["shunned"] = True elif reason == None: user.cache["shunned"] = False else: return "again" return True def reassign_shun(self, user): reason = self.match_shun(user) if reason: user.cache["shunned"] = True else: user.cache["shunned"] = False return None # the xline_rematch hook shouldn't automatically operate on these, so let's make it not. def match_shun(self, user): self.expire_shuns() if "except_line" in user.cache: if user.cache["except_line"]: return None matchMask = "{}@{}".format(user.username, user.hostname) for mask, linedata in self.shunList.iteritems(): if fnmatch(matchMask, mask): return linedata["reason"] matchMask = "{}@{}".format(user.username, user.ip) for mask, linedata in self.shunList.iteritems(): if fnmatch(matchMask, mask): return linedata["reason"] return None elif "shunned" in user.cache: if user.cache["shunned"]: return "Shunned" return None else: matchMask = "{}@{}".format(user.username, user.hostname) for mask in self.shunList.iterkeys(): if fnmatch(matchMask, mask): user.cache["shunned"] = True return "" matchMask = "{}@{}".format(user.username, user.ip) for mask in self.shunList.iterkeys(): if fnmatch(matchMask, mask): user.cache["shunned"] = True return "" user.cache["shunned"] = False return None def expire_shuns(self): current_time = epoch(now()) expired = [] for mask, linedata in self.shunList.iteritems(): if linedata["duration"] and current_time > linedata["created"] + linedata["duration"]: expired.append(mask) for mask in expired: del self.shunList[mask] def check_command(self, user, command, data): if "shunned" not in user.cache or not user.cache["shunned"]: return data if command not in self.ircd.servconfig["shun_command_list"]: return {} return data
class KlineCommand(Command): def __init__(self): self.banList = CaseInsensitiveDictionary() 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 processParams(self, user, params): if user.registered > 0: user.sendMessage(irc.ERR_NOTREGISTERED, "KLINE", ":You have not registered") return {} if "o" not in user.mode: user.sendMessage(irc.ERR_NOPRIVILEGES, ":Permission denied - You do not have the correct operator privileges") return {} if not params: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} banmask = params[0] if banmask in self.ircd.users: banmask = "{}@{}".format(user.username, user.hostname) elif "@" not in banmask: banmask = "*@{}".format(banmask) self.expire_klines() if banmask[0] == "-": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} if banmask not in self.banList: user.sendMessage("NOTICE", ":*** K:line for {} does not currently exist; check /stats K for a list of active k:lines".format(banmask)) return {} return { "user": user, "mask": banmask } if len(params) < 3 or not params[2]: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} if banmask[0] == "+": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "KLINE", ":Not enough parameters") return {} if banmask in self.banList: user.sendMessage("NOTICE", ":*** There's already a k:line set on {}! Check /stats K for a list of active k:lines.".format(banmask)) return {} return { "user": user, "mask": banmask, "duration": parse_duration(params[1]), "reason": " ".join(params[2:]) } def statsList(self, user, statsType): if statsType != "K": return self.expire_klines() for mask, linedata in self.banList.iteritems(): user.sendMessage(irc.RPL_STATSKLINE, ":{} {} {} {} :{}".format(mask, linedata["created"], linedata["duration"], linedata["setter"], linedata["reason"])) def register_check(self, user): result = self.match_kline(user) if not result: if result == None: return True return "again" user.sendMessage("NOTICE", ":{}".format(self.ircd.servconfig["client_ban_msg"])) user.sendMessage("ERROR", ":Closing Link: {} [K:Lined: {}]".format(user.hostname, result), to=None, prefix=None) return False def match_kline(self, user): if "o" in user.mode: return None # don't allow bans to affect opers if user.server != self.ircd.name: return None # only match users on this server if "except_line" not in user.cache: if "kline_match" in user.cache: return user.cache["kline_match"] # Determine whether the user matches self.expire_klines() match_against = irc_lower("{}@{}".format(user.username, user.hostname)) for mask, linedata in self.banList.iteritems(): if fnmatch(match_against, mask): user.cache["kline_match"] = linedata["reason"] return "" match_against = irc_lower("{}@{}".format(user.username, user.ip)) for mask in self.banList.iterkeys(): # we just removed expired lines if fnmatch(match_against, mask): user.cache["kline_match"] = linedata["reason"] return "" return None else: if user.cache["except_line"]: return None if "kline_match" in user.cache: return user.cache["kline_match"] self.expire_klines() match_against = irc_lower("{}@{}".format(user.username, user.hostname)) for mask, linedata in self.banList.iteritems(): if fnmatch(match_against, mask): return linedata["reason"] match_against = irc_lower("{}@{}".format(user.username, user.ip)) for mask in self.banList.iterkeys(): # we just removed expired lines if fnmatch(match_against, mask): return linedata["reason"] return None def expire_klines(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]
class ShunCommand(Command): def __init__(self): self.shunList = CaseInsensitiveDictionary() 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 processParams(self, user, params): if user.registered > 0: user.sendMessage(irc.ERR_NOTREGISTERED, "SHUN", ":You have not registered") return {} if "o" not in user.mode: user.sendMessage( irc.ERR_NOPRIVILEGES, ":Permission denied - You do not have the correct operator privileges" ) return {} if not params: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} banmask = params[0] if banmask in self.ircd.users: udata = self.ircd.users[banmask] banmask = "{}@{}".format(udata.username, udata.hostname) elif "@" not in banmask: banmask = "*@{}".format(banmask) self.expire_shuns() if banmask[0] == "-": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} if banmask not in self.shunList: user.sendMessage( "NOTICE", ":*** Shun {} not found; check /stats S for a list of active shuns." .format(banmask)) return {} return {"user": user, "mask": banmask} if len(params) < 3 or not params[2]: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} if banmask[0] == "+": banmask = banmask[1:] if not banmask: user.sendMessage(irc.ERR_NEEDMOREPARAMS, "SHUN", ":Not enough parameters") return {} if banmask in self.shunList: user.sendMessage( "NOTICE", ":*** Shun {} is already set! Check /stats S for a list of active shuns." .format(banmask)) return {} return { "user": user, "mask": banmask, "duration": parse_duration(params[1]), "reason": " ".join(params[2:]) } def statsList(self, user, statsType): if statsType != "S": return self.expire_shuns() for mask, linedata in self.shunList.iteritems(): user.sendMessage( irc.RPL_STATSSHUN, "{} {} {} {} :{}".format(mask, linedata["created"], linedata["duration"], linedata["setter"], linedata["reason"])) def check_register(self, user): reason = self.match_shun(user) if reason: user.cache["shunned"] = True elif reason == None: user.cache["shunned"] = False else: return "again" return True def reassign_shun(self, user): reason = self.match_shun(user) if reason: user.cache["shunned"] = True else: user.cache["shunned"] = False return None # the xline_rematch hook shouldn't automatically operate on these, so let's make it not. def match_shun(self, user): self.expire_shuns() if "except_line" in user.cache: if user.cache["except_line"]: return None matchMask = "{}@{}".format(user.username, user.hostname) for mask, linedata in self.shunList.iteritems(): if fnmatch(matchMask, mask): return linedata["reason"] matchMask = "{}@{}".format(user.username, user.ip) for mask, linedata in self.shunList.iteritems(): if fnmatch(matchMask, mask): return linedata["reason"] return None elif "shunned" in user.cache: if user.cache["shunned"]: return "Shunned" return None else: matchMask = "{}@{}".format(user.username, user.hostname) for mask in self.shunList.iterkeys(): if fnmatch(matchMask, mask): user.cache["shunned"] = True return "" matchMask = "{}@{}".format(user.username, user.ip) for mask in self.shunList.iterkeys(): if fnmatch(matchMask, mask): user.cache["shunned"] = True return "" user.cache["shunned"] = False return None def expire_shuns(self): current_time = epoch(now()) expired = [] for mask, linedata in self.shunList.iteritems(): if linedata["duration"] and current_time > linedata[ "created"] + linedata["duration"]: expired.append(mask) for mask in expired: del self.shunList[mask] def check_command(self, user, command, data): if "shunned" not in user.cache or not user.cache["shunned"]: return data if command not in self.ircd.servconfig["shun_command_list"]: return {} return data