Exemplo n.º 1
0
            # Get the punishment and reason.
            punishment = mhl_settings.get('punishment', MASSHIGHLIGHT_DEFAULTS['punishment']).lower()
            reason = mhl_settings.get('reason', MASSHIGHLIGHT_DEFAULTS['reason'])

            log.info("(%s) antispam: punishing %s => %s for mass highlight spam",
                     irc.name,
                     irc.get_friendly_name(source),
                     channel)
            punished = _punish(irc, source, channel, punishment, reason)
            break

    log.debug('(%s) antispam.masshighlight: got %s/%s nicks on message to %r', irc.name,
              len(nicks_caught), min_nicks, channel)
    return not punished  # Filter this message from relay, etc. if it triggered protection

utils.add_hook(handle_masshighlight, 'PRIVMSG', priority=1000)
utils.add_hook(handle_masshighlight, 'NOTICE', priority=1000)

TEXTFILTER_DEFAULTS = {
    'reason': "Spam is prohibited",
    'punishment': 'kick+ban+block',
    'watch_pms': False,
    'enabled': False,
    'munge_unicode': True,
}
def handle_textfilter(irc, source, command, args):
    """Antispam text filter handler."""
    target = args['target']
    text = args['text']
    txf_settings = irc.get_service_option('antispam', 'textfilter',
                                          TEXTFILTER_DEFAULTS)
Exemplo n.º 2
0
    staffchans = irc.get_service_option('operlock', 'channels', default=None) or []
    staffchans = list(map(irc.to_lower, staffchans))
    if not staffchans:
        return
    elif not _should_enforce(irc, source, args):
        return

    for channel in args['channels']:
        if irc.to_lower(channel) in staffchans and irc.is_oper(source):
            if irc.protoname in ('inspircd', 'unreal'):
                irc.msg(source, "Warning: You must deoper to leave %r." % channel, notice=True)
                irc._send_with_prefix(irc.sid, 'SAJOIN %s %s' % (source, channel))
            else:
                log.warning('(%s) Force join is not supported on this IRCd %r!', irc.name, irc.protoname)

utils.add_hook(handle_part, 'PART')

DEOPER_KICK_REASON = 'User has deopered'
def handle_mode(irc, source, command, args):
    """Kicks users who deoper from designated staff channels."""
    staffchans = irc.get_service_option('operlock', 'channels', default=None) or []
    staffchans = list(map(irc.to_lower, staffchans))
    if not staffchans:
        return
    elif not _should_enforce(irc, source, args):
        return

    if ('-o', None) in args['modes']:
        # User is deopering
        for channel in irc.users[source].channels:
            if irc.to_lower(channel) in staffchans:
Exemplo n.º 3
0
    # irc.pseudoclient stores the IrcUser object of the main PyLink client.
    # (i.e. the user defined in the bot: section of the config)
    if 'used REGISTER on' in text and channel == '#debug':
        nick = text.split()
        nick = nick[1]
        nick = nick.split('!')
        nick = nick[0]

        regchannel = text.split()
        regchannel = regchannel[6]
        irc.proto.join(weuid, regchannel)
        irc.proto.message(weuid, regchannel,
                          'Welcome to ElectroCode, %s' % nick)
        irc.proto.message(
            weuid, regchannel,
            "I've auto-assigned a bot for you to use. If you want a different one, you can look at '/bs botlist'."
        )
        irc.proto.message(weuid, regchannel,
                          "If you have any problems, please join '#help'.")
        irc.proto.message(weuid, regchannel,
                          "If you've seen this before, just ignore me.")
        irc.proto.part(weuid, regchannel, "Welcome")


utils.add_hook(hook_privmsg, 'PRIVMSG')


def die(irc):
    utils.unregisterService('welcome')
Exemplo n.º 4
0
    for chan in channels:
        if utils.isChannel(chan):
            irc.proto.join(u, chan)
            irc.callHooks([
                irc.sid, 'PYLINK_SERVICE_JOIN', {
                    'channel': chan,
                    'users': [u]
                }
            ])
        else:
            log.warning('(%s) Ignoring invalid autojoin channel %r.', irc.name,
                        chan)


utils.add_hook(spawn_service, 'PYLINK_NEW_SERVICE')


def handle_disconnect(irc, source, command, args):
    """Handles network disconnections."""
    for name, sbot in world.services.items():
        try:
            del sbot.uids[irc.name]
            log.debug(
                "coremods.service_support: removing uids[%s] from service bot %s",
                irc.name, sbot.name)
        except KeyError:
            continue


utils.add_hook(handle_disconnect, 'PYLINK_DISCONNECT')
Exemplo n.º 5
0
            quote.join(irc, "%s" % channel)
            if channel_row:
                pass
            else:
                ins = dbc.insert().values(id=channel_id,
                                          channel=channel,
                                          added_by=irc.getHostmask(source),
                                          private=options.private,
                                          mode=options.mode,
                                          invited=0)
                result = engine.execute(ins).rowcount
                if result > 0:
                    log.info("Joined %s due to invite." % channel)


utils.add_hook(hook_invite, "INVITE")

##
#
#  End Admin Commands
#
####
#
#  Maintenance Commands
#
##
join_parser = utils.IRCParser()
join_parser.add_argument("channel", type=str)
join_parser.add_argument("-p", "--private", default=0, choices=[0, 1])
join_parser.add_argument("-m",
                         "--mode",
Exemplo n.º 6
0
            irc.callHooks([
                source, 'PYLINK_CUSTOM_WHOIS', {
                    'target': target,
                    'server': server
                }
            ])
        else:
            log.debug(
                '(%s) coremods.handlers.handle_whois: skipping custom whois handlers because '
                'caller %s is marked as a bot', irc.name, source)

    # 318: End of WHOIS.
    f(318, source, "%s :End of /WHOIS list" % nick)


utils.add_hook(handle_whois, 'WHOIS')


def handle_mode(irc, source, command, args):
    """Protect against forced deoper attempts."""
    target = args['target']
    modes = args['modes']
    # If the sender is not a PyLink client, and the target IS a protected
    # client, revert any forced deoper attempts.
    if irc.isInternalClient(target) and not irc.isInternalClient(source):
        if ('-o', None) in modes and (target == irc.pseudoclient.uid or
                                      not irc.isManipulatableClient(target)):
            irc.proto.mode(irc.sid, target, {('+o', None)})


utils.add_hook(handle_mode, 'MODE')
Exemplo n.º 7
0
        # :charybdis.midnight.vpn 317 jlu5 jlu5 1946 1499867833 :seconds idle, signon time
        if irc.get_service_bot(target) and conf.conf['pylink'].get('whois_show_startup_time', True):
            f(317, source, "%s 0 %s :seconds idle (placeholder), signon time" % (nick, irc.start_ts))

        # Call custom WHOIS handlers via the PYLINK_CUSTOM_WHOIS hook, unless the
        # caller is marked a bot and the whois_show_extensions_to_bots option is False
        if (source_is_bot and conf.conf['pylink'].get('whois_show_extensions_to_bots')) or (not source_is_bot):
            irc.call_hooks([source, 'PYLINK_CUSTOM_WHOIS', {'target': target, 'server': server}])
        else:
            log.debug('(%s) coremods.handlers.handle_whois: skipping custom whois handlers because '
                      'caller %s is marked as a bot', irc.name, source)

    # 318: End of WHOIS.
    f(318, source, "%s :End of /WHOIS list" % nick)
utils.add_hook(handle_whois, 'WHOIS')

def handle_mode(irc, source, command, args):
    """Protect against forced deoper attempts."""
    target = args['target']
    modes = args['modes']
    # If the sender is not a PyLink client, and the target IS a protected
    # client, revert any forced deoper attempts.
    if irc.is_internal_client(target) and not irc.is_internal_client(source):
        if ('-o', None) in modes and (target == irc.pseudoclient.uid or not irc.is_manipulatable_client(target)):
            irc.mode(irc.sid, target, {('+o', None)})
utils.add_hook(handle_mode, 'MODE')

def handle_operup(irc, source, command, args):
    """Logs successful oper-ups on networks."""
    otype = args.get('text', 'IRC Operator')
Exemplo n.º 8
0
    # Store the service name in the User object for easier access.
    userobj.service = name

    sbot.uids[irc.name] = u = userobj.uid

    # Special case: if this is the main PyLink client being spawned,
    # assign this as irc.pseudoclient.
    if name == 'pylink' and not irc.pseudoclient:
        log.debug('(%s) spawn_service: irc.pseudoclient set to UID %s', irc.name, u)
        irc.pseudoclient = userobj

    # Enumerate & join network defined channels.
    sbot.join(irc, sbot.get_persistent_channels(irc))

utils.add_hook(spawn_service, 'PYLINK_NEW_SERVICE')

def handle_disconnect(irc, source, command, args):
    """Handles network disconnections."""
    for name, sbot in world.services.items():
        try:
            del sbot.uids[irc.name]
            log.debug("coremods.service_support: removing uids[%s] from service bot %s", irc.name, sbot.name)
        except KeyError:
            continue

utils.add_hook(handle_disconnect, 'PYLINK_DISCONNECT')

def handle_endburst(irc, source, command, args):
    """Handles network bursts."""
    if source == irc.uplink:
Exemplo n.º 9
0
    reason = irc.get_service_option('sshbl', 'reason',
        "Your host runs an SSH daemon commonly used by spammer IPs. Consider upgrading your machines "
        "or contacting network staff for an exemption.")

    if result:
        _, port, blacklisted, score = result
        if not blacklisted:
            return
        log.info("sshbl: caught IP %s:%s (%s/%s) with score %s", ip, port, irc.name, args['nick'], score)
        if args['uid'] in irc.users:
            irc.kill(irc.pseudoclient.uid, args['uid'], reason)

def handle_uid(irc, source, command, args):
    """Checks incoming connections against SSHBL."""
    ip = args['ip']
    exemptions = irc.get_service_option('sshbl', 'exempt_hosts', default=None) or []
    if not irc.connected.is_set():
        # Don't scan users until we've finished bursting.
        return
    elif not ipaddress.ip_address(ip).is_global:
        log.debug("sshbl: skipping scanning local address %s", ip)
        return
    elif args['uid'] in irc.users and exemptions:
        for glob in exemptions:
            if irc.match_host(glob, args['uid']):
                log.debug("sshbl: skipping scanning exempt address %s (%s/%s)", ip, irc.name, args['nick'])
                return
    pool.submit(_check_connection, irc, args)

utils.add_hook(handle_uid, 'UID')
Exemplo n.º 10
0
                    # Ignore if no nicks are affected on the channel.
                    if not nicklist:
                        continue

                    colored_nicks = [color_text(nick) for nick in nicklist]

                    # Join both the nicks and colored_nicks fields into a comma separated string.
                    cargs['nicks'] = ', '.join(nicklist)
                    cargs['colored_nicks'] = ', '.join(colored_nicks)

                text = text_template.safe_substitute(cargs)
                # PMs are always sent as notice - this prevents unknown command loops with bots.
                irc.msg(target, text, loopback=False, notice=private)


utils.add_hook(cb_relay_core, 'CLIENTBOT_MESSAGE')
utils.add_hook(cb_relay_core, 'CLIENTBOT_KICK')
utils.add_hook(cb_relay_core, 'CLIENTBOT_PART')
utils.add_hook(cb_relay_core, 'CLIENTBOT_JOIN')
utils.add_hook(cb_relay_core, 'CLIENTBOT_QUIT')
utils.add_hook(cb_relay_core, 'CLIENTBOT_NICK')
utils.add_hook(cb_relay_core, 'CLIENTBOT_SJOIN')
utils.add_hook(cb_relay_core, 'CLIENTBOT_SQUIT')


@utils.add_cmd
def rpm(irc, source, args):
    """<target> <text>

    Sends PMs to users over the relay, if Clientbot PMs are enabled.
    """
Exemplo n.º 11
0
                if irc.is_oper(user):
                    irc.msg(user, "Warning: %s kills unopered users!" % channel,
                            notice=True,
                            source=asm_uid or irc.pseudoclient.uid)
                else:
                    log.info('(%s) badchans: punishing user %s (server: %s) for joining channel %s',
                             irc.name, nuh, irc.get_friendly_name(irc.get_server(user)), channel)
                    if use_kline:
                        irc.set_server_ban(asm_uid or irc.sid, kline_duration, host=ip, reason=REASON)
                    else:
                        irc.kill(asm_uid or irc.sid, user, REASON)

                    if ip not in seen_ips:
                        dronebl_key = irc.get_service_option('badchans', 'dronebl_key')
                        if dronebl_key:
                            log.info('(%s) badchans: submitting IP %s (%s) to DroneBL', irc.name, ip, nuh)
                            pool.submit(_submit_dronebl, irc, ip, dronebl_key, nuh)

                        dnsblim_key = irc.get_service_option('badchans', 'dnsblim_key')
                        if dnsblim_key:
                            log.info('(%s) badchans: submitting IP %s (%s) to DNSBL.im', irc.name, ip, nuh)
                            pool.submit(_submit_dnsblim, irc, ip, dnsblim_key, nuh)

                        seen_ips[ip] = time.time()

                    else:
                        log.debug('(%s) badchans: ignoring already submitted IP %s', irc.name, ip)

utils.add_hook(handle_join, 'JOIN')
Exemplo n.º 12
0
            # Note, do NOT use irc.reply() in hook handlers because nothing except the
            # command handler system actually updates the last caller.
            irc.msg(source,
                    '\x01%s %s\x01' % (ctcp_command, result),
                    notice=True,
                    source=target)

        return False  # Block this message from reaching the general command handler
    else:
        log.info('(%s) Received unknown CTCP %s from %s to %s', irc.name,
                 ctcp_command, irc.get_hostmask(source),
                 irc.get_friendly_name(target))
        return False


utils.add_hook(handle_ctcp, 'PRIVMSG', priority=200)


def handle_ctcpversion(irc, source, ctcp, data):
    """
    Handles CTCP version requests.
    """
    return irc.version()


def handle_ctcpeaster(irc, source, ctcp, data):
    """
    Secret easter egg.
    """

    responses = ["Legends say the cord monster was born only %s years ago..." % \
Exemplo n.º 13
0
            irc.proto.updateClient(target, 'HOST', new_host)

            # Only operate on the first match.
            break


def handle_uid(irc, sender, command, args):
    """
    Changehost listener for new connections.
    """

    target = args['uid']
    _changehost(irc, target, args)


utils.add_hook(handle_uid, 'UID')


@utils.add_cmd
def applyhosts(irc, sender, args):
    """[<network>]

    Applies all configured hosts for users on the given network, or the current network if none is specified."""

    try:  # Try to get network from the command line.
        network = world.networkobjects[args[0]]
    except IndexError:  # No network was given
        network = irc
    except KeyError:  # Unknown network
        irc.reply("Error: Unknown network '%s'." % network)
        return
Exemplo n.º 14
0
    Tracks kills against PyLink clients. If too many are received,
    automatically disconnects from the network.
    """

    if (args['userdata'] and irc.isInternalServer(
            args['userdata'].server)) or irc.isInternalClient(args['target']):
        if killcache.setdefault(irc.name, 1) >= length:
            log.error('(%s) servprotect: Too many kills received, aborting!',
                      irc.name)
            irc.disconnect()

        log.debug('(%s) servprotect: Incrementing killcache by 1', irc.name)
        killcache[irc.name] += 1


utils.add_hook(handle_kill, 'KILL')


def handle_save(irc, numeric, command, args):
    """
    Tracks SAVEs (nick collision) against PyLink clients. If too many are received,
    automatically disconnects from the network.
    """
    if irc.isInternalClient(args['target']):
        if savecache.setdefault(irc.name, 0) >= length:
            log.error('(%s) servprotect: Too many nick collisions, aborting!',
                      irc.name)
            irc.disconnect()

        log.debug('(%s) servprotect: Incrementing savecache by 1', irc.name)
        savecache[irc.name] += 1
Exemplo n.º 15
0
            # We're cramming as much as we can into the class field...
            _num(
                213, "C %s * %s %s [%s:%s:%s]" %
                (serverdata.get('ip', '0.0.0.0'), netname,
                 serverdata.get('port', 0), serverdata['protocol'],
                 'ssl' if serverdata.get('ssl') else 'no-ssl',
                 serverdata.get('encoding', 'utf-8')))
    elif stats_type == 'o':
        # 243/RPL_STATSOLINE: "O <hostmask> * <nick> [:<info>]"
        # New style accounts only!
        for accountname, accountdata in conf.conf['login'].get('accounts',
                                                               {}).items():
            networks = accountdata.get('networks', [])
            if irc.name in networks or not networks:
                hosts = ' '.join(accountdata.get('hosts', ['*@*']))
                needoper = 'needoper' if accountdata.get(
                    'require_oper') else ''
                _num(243, "O %s * %s :%s" % (hosts, accountname, needoper))

    elif stats_type == 'u':
        # 242/RPL_STATSUPTIME: ":Server Up <days> days <hours>:<minutes>:<seconds>"
        _num(242, ':Server Up %s' % timediff(world.start_ts, int(time.time())))

    else:
        log.info('(%s) Unknown /STATS type %r requested by %s', irc.name,
                 stats_type, irc.get_hostmask(source))
    _num(219, "%s :End of /STATS report" % stats_type)


utils.add_hook(handle_stats, 'STATS')
Exemplo n.º 16
0
            'modes': outgoing_modes,
            'parse_as': 'MODE'
        }
    ])


def handle_join(irc, source, command, args):
    """
    Automode JOIN listener. This sets modes accordingly if the person joining matches a mask in the
    ACL.
    """
    channel = irc.toLower(args['channel'])
    match(irc, channel, args['users'])


utils.add_hook(handle_join, 'JOIN')
utils.add_hook(handle_join,
               'PYLINK_RELAY_JOIN')  # Handle the relay version of join
utils.add_hook(handle_join,
               'PYLINK_SERVICE_JOIN')  # And the version for service bots


def handle_services_login(irc, source, command, args):
    """
    Handles services login change, to trigger Automode matching.
    """
    for channel in irc.users[source].channels:
        # Look at all the users' channels for any possible changes.
        match(irc, channel, [source])

Exemplo n.º 17
0
                irc.update_client(target, 'HOST', new_host)

            # Only operate on the first match.
            break


def handle_uid(irc, sender, command, args):
    """
    Changehost listener for new connections.
    """

    target = args['uid']
    _changehost(irc, target, args)


utils.add_hook(handle_uid, 'UID')


def handle_chghost(irc, sender, command, args):
    """
    Handles incoming CHGHOST requests for optional host-change enforcement.
    """
    changehost_conf = conf.conf.get("changehost")
    if not changehost_conf:
        return

    target = args['target']

    if (not irc.is_internal_client(sender)) and (
            not irc.is_internal_server(sender)):
        if irc.name in changehost_conf.get('enforced_nets', []):
Exemplo n.º 18
0
                # Try to look up a prefix specific for this bot in
                # bot: prefixes: <botname>, falling back to the default prefix if not
                # specified.
                prefixes = [irc.botdata.get('prefixes', {}).get(botname) or
                            irc.botdata.get('prefix')]

                # If responding to nick is enabled, add variations of the current nick
                # to the prefix list: "<nick>," and "<nick>:"
                nick = irc.users[servuid].nick

                if respondtonick:
                    prefixes += [nick+',', nick+':']

                if not any(prefixes):
                    # We finished with an empty prefixes list, meaning fantasy is misconfigured!
                    log.warning("(%s) Fantasy prefix for bot %s was not set in configuration - "
                                "fantasy commands will not work!", irc.name, botname)
                    continue

                for prefix in prefixes:  # Cycle through the prefixes list we finished with.
                     if prefix and orig_text.startswith(prefix):

                        # Cut off the length of the prefix from the text.
                        text = orig_text[len(prefix):]

                        # Finally, call the bot command and loop to the next bot.
                        sbot.call_cmd(irc, source, text, called_in=channel)
                        continue

utils.add_hook(handle_fantasy, 'PRIVMSG')
Exemplo n.º 19
0
    result = result.split()
    result = result[1:]
    result = (" ").join(result)
    result = result.strip('\x01')
    if nowts <= nickts + 15:
        if nicksid in oursids:
            myuid = ctcp.uids.get(irc.name)
            if args['text'].startswith('\x01') and args['text'].endswith(
                    '\x01'):
                irc.proto.message(
                    myuid, '#debug',
                    "Received VERSION reply from %s, using: %s" %
                    (irc.getFriendlyName(source), result))


utils.add_hook(hook_connversion, 'NOTICE')


def hook_uid(irc, source, command, args):
    try:
        myuid = ctcp.uids.get(irc.name)
        oursids = irc.serverdata.get('sids', [])
        nick = args['nick']
        nickuid = args['uid']
        nowts = int(time.time())
        theirts = int(args['ts'])

        if source in oursids:
            irc.proto.message(myuid, nickuid, "\x01VERSION\x01")
    except LookupError:
        pass