Exemple #1
0
def m_sasl_plain(info):
    cli = info['source']
    data = info['data']

    account, authorization_id, passphrase = data.split(b'\x00')
    account = str(account, 'utf8')
    passphrase = str(passphrase, 'utf8')

    account_info = cli.ctx.data.get('account.{}'.format(account), None)
    if (account_info and 'passphrase' in account_info['credentials']
            and account_info['verified']):
        passphrase_hash = account_info['credentials']['passphrase']
        if cli.ctx.hashing.verify(passphrase, passphrase_hash):
            cli.account = account
            eventmgr_core.dispatch('account change', {
                'source': cli,
                'account': account,
            })
            cli.sasl = None
            hostmask = cli.hostmask
            if hostmask is None:
                hostmask = '*'
            cli.dump_numeric('900', [
                hostmask, account,
                'You are now logged in as {}'.format(account)
            ])
            cli.dump_numeric('903', ['SASL authentication successful'])
            return
    cli.dump_numeric('904', ['SASL authentication failed'])
Exemple #2
0
def m_PRIVMSG(cli, ev_msg):
    targetlist = ev_msg["params"][0].split(",")
    message = ev_msg["params"][1]

    for target in targetlist:
        if target[0] != "#":
            cli_tg = cli.ctx.clients.get(target, None)
            if not cli_tg:
                cli.dump_numeric("401", [target, "No such nick/channel"])
                continue
            eventmgr_core.dispatch(
                "client message", {"source": cli, "target": cli_tg, "target_name": target, "message": message}
            )
            continue

        ch = cli.ctx.chmgr.get(target)
        if not ch:
            cli.dump_numeric("401", [target, "No such nick/channel"])
            continue

        if not ch.can_send(cli):
            cli.dump_numeric("404", [ch.name, "Cannot send to channel"])
            continue

        eventmgr_core.dispatch(
            "channel message", {"source": cli, "target": ch, "target_name": target, "message": message}
        )
Exemple #3
0
def m_PRIVMSG(cli, ev_msg):
    targetlist = ev_msg['params'][0].split(',')
    message = ev_msg['params'][1]

    for target in targetlist:
        if target[0] != '#':
            cli_tg = cli.ctx.clients.get(target, None)
            if not cli_tg:
                cli.dump_numeric('401', [target, 'No such nick/channel'])
                continue
            eventmgr_core.dispatch(
                'client message', {
                    'source': cli,
                    'target': cli_tg,
                    'target_name': target,
                    'message': message,
                })
            continue

        ch = cli.ctx.chmgr.get(target)
        if not ch:
            cli.dump_numeric('401', [target, 'No such nick/channel'])
            continue

        if not ch.can_send(cli):
            cli.dump_numeric('404', [ch.name, 'Cannot send to channel'])
            continue

        eventmgr_core.dispatch(
            'channel message', {
                'source': cli,
                'target': ch,
                'target_name': target,
                'message': message,
            })
Exemple #4
0
def m_CAP_REQ(cli, ev_msg):
    cap_add = []
    cap_del = []
    args = ev_msg['params'][1]

    def dump_NAK(cli):
        cli.dump_numeric('CAP', ['NAK', args + ' '])

    for arg in args.split():
        negate = arg[0] == '-'

        if negate:
            arg = arg[1:]

        if arg not in caplist:
            dump_NAK(cli)
            return

        if negate:
            if arg not in cli.caps:
                dump_NAK(cli)
                return
            cap_del.append(arg)
            continue

        if arg in cli.caps:
            dump_NAK(cli)
            return

        cap_add.append(arg)

    cli.dump_numeric('CAP',
                     ['ACK', ' '.join(cap_add) + ' -'.join(cap_del) + ' '])

    # we accepted the changeset, so apply it
    info = {
        'client': cli,
        'caps': cap_add,
    }
    eventmgr_core.dispatch('cap add', info)

    info = {
        'client': cli,
        'caps': cap_del,
    }
    eventmgr_core.dispatch('cap del', info)
Exemple #5
0
def m_CAP_REQ(cli, ev_msg):
    cap_add = []
    cap_del = []
    args = ev_msg["params"][1]

    def dump_NAK(cli):
        cli.dump_numeric("CAP", ["NAK", args + " "])

    for arg in args.split():
        negate = arg[0] == "-"

        if negate:
            arg = arg[1:]

        if arg not in caplist:
            dump_NAK(cli)
            return

        if negate:
            if arg not in cli.caps:
                dump_NAK(cli)
                return
            cap_del.append(arg)
            continue

        if arg in cli.caps:
            dump_NAK(cli)
            return

        cap_add.append(arg)

    cli.dump_numeric("CAP", ["ACK", " ".join(cap_add) + " -".join(cap_del) + " "])

    # we accepted the changeset, so apply it
    info = {"client": cli, "caps": cap_add}
    eventmgr_core.dispatch("cap add", info)

    info = {"client": cli, "caps": cap_del}
    eventmgr_core.dispatch("cap del", info)
Exemple #6
0
def m_reg_create_empty(info):
    cli = info['source']

    cli.ctx.data.put('account.{}'.format(info['account']), {
        'account': info['account'],
        'credentials': {
            'passphrase': cli.ctx.hashing.encrypt(info['credential']),
        },
        'registered_ts': cli.ctx.current_ts,
        'registered_by': cli.hostmask,
        'verified': True,
    })

    cli.dump_numeric('920', [info['account'], 'Account created'])
    cli.account = info['account']
    eventmgr_core.dispatch('account change', {
        'source': cli,
        'account': cli.account,
    })
    cli.dump_numeric('900', [cli.hostmask, info['account'],
                             'You are now logged in as {}'.format(info['account'])])
    cli.dump_numeric('903', ['Authentication successful'])
Exemple #7
0
def m_AUTHENTICATE(cli, ev_msg):
    if len(ev_msg['params']) == 1 and ev_msg['params'][0] == '*':
        if getattr(cli, 'sasl', None):
            cli.dump_numeric('906', ['SASL authentication aborted'])
            cli.sasl = None
        else:
            cli.dump_numeric('904', ['SASL authentication failed'])
        return

    if getattr(cli, 'sasl', None):
        if len(ev_msg['params'][0]) > 400:
            cli.dump_numeric('905', ['SASL message too long'])
            cli.sasl = None
            return

        try:
            data = base64.b64decode(ev_msg['params'][0])
        except binascii.Error:
            cli.dump_numeric('904', ['SASL authentication failed'])
            return

        eventmgr_core.dispatch(
            'sasl authenticate {}'.format(cli.sasl.casefold()), {
                'source': cli,
                'mechanism': cli.sasl,
                'data': data,
            })

    else:
        mechanism = ev_msg['params'][0].upper()
        if mechanism in valid_mechanisms:
            cli.sasl = mechanism
            cli.dump_verb('AUTHENTICATE', '+')
        else:
            cli.dump_numeric('904', ['SASL authentication failed'])
            return
Exemple #8
0
def m_REG(cli, ev_msg):
    params = list(ev_msg['params'])
    subcmd = params.pop(0).casefold()

    if subcmd == 'create':
        account = params.pop(0).casefold()

        if account == '*':
            cli.dump_numeric('922', [account, 'Invalid params: "*" is not a valid account name'])
            return

        account_data = cli.ctx.data.get('account.{}'.format(account), {})
        if account_data:
            global verify_timeout_seconds
            if (account_data['verified'] or account_data['registered_ts'] + verify_timeout_seconds > cli.ctx.current_ts):
                cli.dump_numeric('921', [account, 'Account already exists'])
                return
            # account verify expired, delete old account
            if not account_data['verified']:
                cli.ctx.data.delete('account.{}'.format(account))

        global enabled_cb_types
        callback = params.pop(0).casefold()
        if callback == '*':
            cb_namespace = '*'
            callback = None,
        elif ':' in callback:
            cb_namespace, callback = callback.split(':', 1)
        else:
            # as in the spec, default to the first advertised callback type
            if enabled_cb_types[0] == 'none' and len(enabled_cb_types) > 1:
                cb_namespace = enabled_cb_types[1]
            else:
                cb_namespace = enabled_cb_types[0]

        if cb_namespace not in enabled_cb_types:
            cli.dump_numeric('929', [account, cb_namespace, 'Callback token is invalid'])
            return

        if len(params) > 1:
            cred_type, credential = params[:2]
        elif len(params) == 1:
            cred_type = 'passphrase'
            credential = params.pop(0)
        else:
            cli.dump_numeric('461', [ev_msg['verb'], 'Not enough parameters'])
            return

        global supported_cred_types
        if cred_type not in supported_cred_types:
            cli.dump_numeric('928', [account, cred_type, 'Credential type is invalid'])
            return

        eventmgr_core.dispatch('reg callback {}'.format(cb_namespace), {
            'source': cli,
            'account': account,
            'callback': callback,
            'cb_namespace': cb_namespace,
            'cred_type': cred_type,
            'credential': credential,
        })
    elif subcmd == 'verify':
        account = params.pop(0).casefold()

        account_info = cli.ctx.data.get('account.{}'.format(account), None)

        if account_info:
            if account_info['verified']:
                cli.dump_numeric('924', [account, 'Account already verified'])
                return

            auth_code = params.pop(0)

            if auth_code == account_info['auth_code']:
                account_info['verified'] = True
                del account_info['auth_code']
                cli.ctx.data.put('account.{}'.format(account), account_info)

                cli.dump_numeric('923', [account, 'Account verification successful'])
                cli.account = account
                eventmgr_core.dispatch('account change', {
                    'source': cli,
                    'account': account,
                })
                cli.dump_numeric('900', [cli.hostmask, account,
                                         'You are now logged in as {}'.format(account)])
                cli.dump_numeric('903', ['Authentication successful'])
            else:
                cli.dump_numeric('925', [account, 'Invalid verification code'])
        else:
            cli.dump_numeric('400', ['REG', 'VERIFY', 'Account does not exist'])
    else:
        cli.dump_numeric('400', ['REG', ev_msg['params'][0], 'Unknown subcommand'])