Exemplo n.º 1
0
Arquivo: matrix.py Projeto: gofore/x84
def authenticate_user(handle, password):
    """ Return True if the given handle and password are correct. """

    # artificial delay -- this ensures people cannot guess
    # for user accounts, where existing ones would delay a
    # long while, but unknown users are quickly denied.
    artificial_delay = max(1.0, random.randrange(0, unknown_sleep * 100) / 100)

    matching_handle = find_user(handle)
    if matching_handle is None:
        log.debug('Failed login for {handle}: no such user.'
                  .format(handle=handle))
        time.sleep(artificial_delay)
        return False

    elif not password.strip():
        log.debug('Failed login for {handle}: password not provided.'
                  .format(handle=handle))
        time.sleep(artificial_delay)
        return False

    user = get_user(matching_handle)
    if user.auth(password):
        # success !
        log.debug('Login succeeded for {handle}.'
                  .format(handle=handle))
        return user

    log.debug('Failed login for {handle}: wrong password.'
              .format(handle=handle))
    return False
Exemplo n.º 2
0
def main(anonymous=False, new=False, username=''):
    """ Main procedure. """
    from x84.bbs import (
        getsession,
        getterminal,
        find_user,
        get_user,
        User,
    )

    session, term = getsession(), getterminal()
    session.activity = 'sftp'

    if anonymous:
        user = User(u'anonymous')
    else:
        assert not new, ("[email protected] user not supported by SFTP.")

        # ProperCase user-specified handle
        handle = find_user(username)
        assert handle is not None, handle

        # fetch user record
        user = get_user(handle)

    # assign session user, just as top.py function login()
    session.user = user

    while True:
        inp = term.inkey()  # should block indefinately
        log = logging.getLogger(__name__)
        log.warn('Got inkey: {0!r}'.format(inp))
Exemplo n.º 3
0
Arquivo: lc.py Projeto: quastdog/x84
def refresh_opts(pager, handle):
    """ Refresh pager border with command keys available. """
    from x84.bbs import getsession, getterminal, get_user, find_user, Ansi
    session, term = getsession(), getterminal()
    if not handle or not find_user(handle):
        has_plan = 0
    else:
        has_plan = 0 != len(get_user(handle).get('.plan', u'').strip())
    decorate = lambda key, desc: u''.join((
        term.red_underline(key,),
        u':',
        term.yellow(desc.split()[0]), u' ',
        u' '.join(desc.split()[1:]),
        u' ' if len(desc.split()) > 1 else u'',))
    statusline = u''.join((
        term.bold_yellow(u'- '),
        decorate(u'Escape/q', 'Uit'),
        decorate(u'v', 'iEW .PLAN') if has_plan else u'',
        decorate(u'e', 'dit USR') if 'sysop' in session.user.groups else u'',
        term.bold_yellow(u'-'),
    ))
    if len(Ansi(statusline)) < (pager.visible_width - 4):
        return pager.border() + pager.footer(statusline)
    else:
        return pager.border() + pager.footer(term.bold_red('q') + u':uit')
Exemplo n.º 4
0
def locate_user(term, point):
    """ Prompt for search pattern and return discovered User. """
    _color1, _color2, _color3 = [
        getattr(term, _color) for _color in (
            color_lowlight, color_highlight, color_field_edit)]

    # show help
    width = term.width - (point.x * 2)
    help_txt = (u'Enter username or glob pattern.  Press escape to cancel.')
    y_offset = 0
    for y_offset, txt in enumerate(term.wrap(help_txt, width=width)):
        echo(term.move(point.y + y_offset, point.x))
        echo(_color1(txt) + term.clear_eol)
    point_prompt = Point(y=point.y + y_offset + 2, x=point.x)

    editor = LineEditor(nua.username_max_length, colors={'highlight': _color3})
    while True:
        # prompt for handle
        echo(term.move(*point_prompt))
        echo(u'handle: ' + term.clear_eol)
        inp = editor.read()

        point = Point(y=point_prompt.y + 2, x=point.x)
        if inp is None:
            # canceled (escape)
            return
        elif u'*' in inp or u'?' in inp:
            # a glob pattern, fetch all usernames
            handles = fnmatch.filter(list_users(), inp)
            if len(handles) == 0:
                echo(u''.join((term.move(*point),
                               u'No matches for {0}.'.format(_color2(inp)),
                               term.clear_eos)))
            elif len(handles) == 1:
                return get_user(handles[0])
            else:
                matches_text = (
                    u'{0} accounts matched, chose one: {1}.'.format(
                        _color2(str(len(handles))), u', '.join(
                            _color2(handle) for handle in handles)))
                echo(term.move(*point))
                for y_offset, txt in enumerate(
                        term.wrap(matches_text, width=width)):
                    echo(term.move(point.y + y_offset, point.x))
                    echo(txt + term.clear_eol)
                    if point.y + y_offset > term.height - 3:
                        # we simply cannot display anymore
                        break
                echo(term.clear_eos)
        else:
            handle = find_user(inp)
            if handle is not None:
                return get_user(handle)
            echo(u''.join((term.move(*point),
                           u'No matches for {0}.'.format(_color2(inp)),
                           term.clear_eos)))
Exemplo n.º 5
0
Arquivo: userbase.py Projeto: hick/x84
def check_user_password(username, password):
    """ Boolean return when username and password match user record. """
    from x84.bbs import find_user, get_user
    handle = find_user(username)
    if handle is None:
        return False
    user = get_user(handle)
    if user is None:
        return False
    return password and user.auth(password)
Exemplo n.º 6
0
def view_plan(handle):
    """ Display .plan file for handle. """
    from x84.bbs import getterminal, echo, Ansi, get_user, find_user
    term = getterminal()
    echo(u'\r\n\r\n')
    if not find_user(handle):
        echo(Ansi(u'No Plan.'))
    else:
        echo(Ansi(get_user(handle).get('.plan', u'No Plan.')).wrap(term.width))
    echo(u'\r\n')
    pak()
Exemplo n.º 7
0
def matches_email(handle, email):
    """ Return User record for handle if it matches email. """
    matching_handle = find_user(handle)
    user = matching_handle and get_user(matching_handle)
    if not user:
        log.debug("password reset failed, no such user {0} for email {1}.".format(handle, email))
        return False
    elif not user.email.strip():
        log.debug("password reset failed, user {0} has no email on file.".format(handle))
        return False
    elif email.lower() != user.email.lower():
        log.debug("pasword reset failed, email mismatch: {0} != {1}.".format(email, user.email))
        return False

    # success !
    return user
Exemplo n.º 8
0
Arquivo: nua.py Projeto: hick/x84
def validate_handle(user, handle):
    errmsg = None
    if find_user(handle):
        errmsg = u'User by this name already exists.'

    elif len(handle) < username_min_length:
        errmsg = (u'Username too short, must be at least {0} characters.'
                  .format(username_min_length))

    elif handle.lower() in invalid_usernames:
        errmsg = u'Username is not legal form: reserved.'

    elif os.path.sep in handle:
        errmsg = u'Username is not legal form: contains OS path separator.'

    elif not re.match(username_re_validator, handle):
        errmsg = (u'Username fails validation of regular expression, '
                  u'{0!r}.'.format(username_re_validator))

    # No validation error
    return errmsg, 0
Exemplo n.º 9
0
Arquivo: debug.py Projeto: rostob/x84
def merge_mystic():
    """ Example script to merge csv records into userbase. """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import ini, echo, getch, User, get_user, find_user
    import os
    # you must modify variable ``do_write`` to commit changes,
    # csv format; 'user:pass:origin:email\n', in iso8859-1 encoding.
    do_write = False
    inp_file = os.path.join(
        ini.CFG.get('system', 'datapath'),
        'mystic_dat.csv')
    lno = 0
    for lno, line in enumerate(open(inp_file, 'r')):
        handle = line.split(':', 1)[0].strip().decode('iso8859-1')
        attrs = line.rstrip().split(':')[2:]
        (_password, _location, _email) = attrs
        (_password, _location, _email) = (
            _password.strip().decode('iso8859-1'),
            _location.strip().decode('iso8859-1'),
            _email.strip().decode('iso8859-1'))
        echo(u''.join((u'\r\n',
                       handle, u': ',
                       '%d ' % (len(_password)),
                       '%s ' % (_location),
                       '%s ' % (_email),)))
        match = find_user(handle)
        if match is None:
            user = User(handle)
            user.location = _location
            user.email = _email
            user.password = _password
        else:
            user = get_user(match)
        user.groups.add('old-school')
        if do_write:
            user.save()
    echo(u'\r\n\r\n%d lines processed.' % (lno,))
    getch()
Exemplo n.º 10
0
Arquivo: userbase.py Projeto: hick/x84
def check_user_pubkey(username, public_key):
    """ Boolean return when public_key matches user record. """
    from x84.bbs import find_user, get_user
    log = logging.getLogger(__name__)
    handle = find_user(username)
    if handle is None:
        return False
    user_pubkey = get_user(handle).get('pubkey', False)
    if not user_pubkey:
        log.debug('{0} attempted pubkey authentication, '
                  'but no public key on record for the user.'
                  .format(username))
        return False
    try:
        stored_pubkey = parse_public_key(user_pubkey)
    except (ValueError, Exception):
        import sys
        (exc_type, exc_value, exc_traceback) = sys.exc_info()
        log.debug('{0} for stored public key of user {1!r}: '
                  '{2}'.format(exc_type, username, exc_value))
    else:
        return stored_pubkey == public_key
Exemplo n.º 11
0
def set_handle(user):
    """
    Prompt for a user.handle, minumum length.
    """
    # pylint: disable=R0914
    #        Too many local variables
    from x84.bbs import getterminal, echo, ini, LineEditor, find_user
    import os  # os.path.sep not allowed in nicks
    import re
    term = getterminal()
    prompt_handle = u'username: '******'ENtER AN AliAS'
    msg_exists = u'USER EXiStS.'
    msg_tooshort = u'TOO ShORt, MUSt bE At lEASt %s.'
    msg_invalid = u'IllEGAl USERNAME'
    width = ini.CFG.getint('nua', 'max_user')
    min_user = ini.CFG.getint('nua', 'min_user')
    # pylint: disable=E1103
    #         Instance of '_Chainmap' has no 'split' member
    #         (but some types could not be inferred)
    invalid_nicks = ini.CFG.get('nua', 'invalid_handles').split()
    handle_validation = re.compile(ini.CFG.get('nua', 'handle_validation'))
    while True:
        echo(u'\r\n\r\n' + term.clear_eol + term.normal + prompt_handle)
        user.handle = LineEditor(width, user.handle).read()
        if user.handle == u'' or user.handle is None:
            warning(msg_empty)
        elif find_user(user.handle):
            warning(msg_exists)
        elif len(user.handle) < min_user:
            warning(msg_tooshort % min_user)
        elif ((user.handle.lower() in invalid_nicks)
                or os.path.sep in user.handle):
            warning(msg_invalid)
        elif not handle_validation.match(user.handle):
            warning(msg_invalid)
        else:
            return
Exemplo n.º 12
0
Arquivo: nua.py Projeto: tehmaze/x84
def main(handle=u''):
    """
    Main procedure.
    """

    # set syncterm font, if any
    term = getterminal()
    if term.kind == 'ansi':
        echo(syncterm_setfont(syncterm_font))

    # reset handle to an empty string if it is any
    # of the 'new' user account alias strings
    if handle.lower() in new_usernames:
        handle = u''

    user = User(handle)

    # create new user record for manipulation
    while True:
        display_banner(art_file, encoding='ascii')
        user = do_nua(user)

        # user canceled.
        if user is None:
            return

        # confirm
        if prompt_yesno(question='Create account'):
            assert not find_user(user.handle), (
                # prevent race condition, scenario: `billy' begins new account
                # process, waits at 'Create account [yn] ?' prompt until a
                # second `billy' finishes account creation process, then the
                # first `billy' enters 'y', overwriting the existing account.
                'Security race condition: account already exists')
            user.save()
            goto(top_script, user.handle)
Exemplo n.º 13
0
def main(anonymous=False, new=False, username=''):
    """ Main procedure. """
    from x84.bbs import echo, goto, find_user, ini
    topscript = ini.CFG.get('matrix', 'topscript')
    nuascript = ini.CFG.get('nua', 'script')

    # http://www.termsys.demon.co.uk/vtansi.htm
    # disable line-wrapping
    echo(unichr(27) + u'[7l')

    # http://www.xfree86.org/4.5.0/ctlseqs.html
    # Save xterm icon and window title on stack.
    echo(unichr(27) + u'[22;0t')

    if anonymous:
        # user ssh'd in as [email protected]
        goto(topscript, 'anonymous')
    elif new:
        # user ssh'd in as [email protected]
        goto(nuascript)

    handle = find_user(username)
    assert handle is not None, handle
    goto(topscript, handle=handle)
Exemplo n.º 14
0
def get_username(handle=u''):
    """
    Prompt for a login handle. If unfound, script change to 'nua' when
    allow_apply is enabled (default=yes). Also allow 'anonymous' when enabled
    (default=no). A unicode handle of non-zero length is returned when the
    login handle matches a userbase record.
    """
    # pylint: disable=R0914,R0911
    #         Too many local variables
    #         Too many return statements
    from x84.bbs import getterminal, ini, echo, LineEditor, gosub, goto
    from x84.bbs import find_user, getch
    term = getterminal()
    prompt_user = u'\r\n  user: '******'\r\n\r\n  --> Create new account? [ynq]   <--' + '\b' * 5
    allow_apply = ini.CFG.getboolean('nua', 'allow_apply')
    enable_anonymous = ini.CFG.getboolean('matrix', 'enable_anonymous')
    # pylint: disable=E1103
    #         Instance of '_Chainmap' has no 'split' member
    #         (but some types could not be inferred)
    newcmds = ini.CFG.get('matrix', 'newcmds').split()
    byecmds = ini.CFG.get('matrix', 'byecmds').split()
    denied_msg = u'\r\n\r\nfiRSt, YOU MUSt AbANdON YOUR libERtIES.'
    badanon_msg = u"\r\n  " + term.bright_red + u"'%s' login denied."
    max_user = ini.CFG.getint('nua', 'max_user')
    nuascript = ini.CFG.get('nua', 'script')
    topscript = ini.CFG.get('matrix', 'topscript')

    echo(prompt_user)
    handle = LineEditor(max_user, handle).read()
    if handle is None or 0 == len(handle.strip()):
        echo(u'\r\n')
        return u''
    elif handle.lower() in newcmds:
        if allow_apply:
            gosub('nua', u'')
            return u''
        denied(denied_msg)
        return u''
    elif handle.lower() in byecmds:
        goto('logoff')
    elif handle.lower() == u'anonymous':
        if enable_anonymous:
            goto(topscript, 'anonymous')
        denied(badanon_msg % (handle,))
        return u''
    u_handle = find_user(handle)
    if u_handle is not None:
        return u_handle  # matched
    if allow_apply is False:
        denied(denied_msg)
        return u''

    echo(apply_msg)
    ynq = getch()
    if ynq in (u'q', u'Q', term.KEY_EXIT):
        # goodbye
        goto('logoff')
    elif ynq in (u'y', u'Y'):
        # new user application
        goto(nuascript, handle)
    echo(u'\r\n')
    return u''
Exemplo n.º 15
0
def main():
    """ Main procedure. """
    # pylint: disable=R0914,R0911
    #         Too many local variables
    import logging
    from x84.bbs import getsession, getterminal, ini, echo, get_user, goto
    from x84.bbs import find_user, showcp437
    from x84.engine import __url__ as url
    logger = logging.getLogger()
    session, term = getsession(), getterminal()
    session.activity = u'Logging in'
    handle = (session.env.get('USER', '').decode('iso8859-1', 'replace'))
    anon_allowed_msg = u"'%s' login enabled.\r\n" % (
        term.bold_cyan('anonymous',))
    # pylint: disable=E1103
    #         Instance of '_Chainmap' has no 'split' member
    #         (but some types could not be inferred)
    newcmds = ini.CFG.get('matrix', 'newcmds').split()
    apply_msg = u"'%s' to create new account.\r\n" % (
        term.bold_cyan(newcmds[0]),)
    allow_apply = ini.CFG.getboolean('nua', 'allow_apply')
    enable_anonymous = ini.CFG.getboolean('matrix', 'enable_anonymous')
    enable_pwreset = ini.CFG.getboolean('matrix', 'enable_pwreset')
    bbsname = ini.CFG.get('system', 'bbsname')
    artfile = os.path.join(os.path.dirname(__file__), 'art', 'xz-1984.ans')
    topscript = ini.CFG.get('matrix', 'topscript')
    max_tries = 10
    session.flush_event('refresh')
    #uname()
    # display banner
    echo(u''.join((
        term.normal, u'\r\n',
        u'Connected to %s, see %s for source\r\n' % (bbsname, url),)))
    for line in showcp437(artfile):
        echo(line)
    echo(term.normal)
    echo (u''.join((
        u'\r\n\r\n',
        term.bold(u'tERM'), u': ',
        term.cyan_underline(session.env['TERM']),
        u'\r\n',
        term.bold(u'diMENSiONs'), u': ', '%s%s%s' % (
            term.bold_cyan(str(term.width)),
            term.cyan(u'x'),
            term.bold_cyan(str(term.height)),),
        u'\r\n',
        term.bold(u'ENCOdiNG'), u': ',
        term.cyan_underline(session.encoding),
        u'\r\n\r\n',
        anon_allowed_msg if enable_anonymous else u'',
        apply_msg if allow_apply else u'',
    )))
    # http://www.termsys.demon.co.uk/vtansi.htm
    # disable line-wrapping
    echo(unichr(27) + u'[7l')

    # http://www.xfree86.org/4.5.0/ctlseqs.html
    # Save xterm icon and window title on stack.
    echo(unichr(27) + u'[22;0t')

    if handle:
        echo('\r\nHello, %s!' % (handle,))
        match = find_user(handle)
        if match is not None:
            handle = match
        else:
            handle = ''

    # prompt for username & password
    for _num in range(0, max_tries):
        handle = get_username(handle)
        if handle != u'':
            session.activity = u'Logging in'
            user = get_user(handle)
            if try_pass(user):
                goto(topscript, user.handle)
            echo(u'\r\n\r\n')
            if enable_pwreset:
                try_reset(user)
            else:
                logger.info('%r failed password', handle)
    logger.warn('maximum tries exceeded')
    goto('logoff')
Exemplo n.º 16
0
def dummy_pager(last_callers):
    """ Dummy pager for displaying last callers """
    # pylint: disable=R0914
    #         Too many local variables
    from x84.bbs import getterminal, getsession, echo, getch, ini, find_user
    from x84.bbs import LineEditor, Ansi, list_users, get_user, gosub
    session, term = getsession(), getterminal()
    msg_prompt = (
        u'\r\n%sONtiNUE, %stOP, %sON-StOP %siEW .PlAN%s ?\b\b' % (
        term.bold(u'[c]'),
        term.bold(u'[s]'),
        term.bold(u'n'),
        term.bold(u'[v]'),
        u' [e]dit USR' if (
        'sysop' in session.user.groups) else u'',))
    msg_partial = u'PARtiAl MAtChES'
    msg_prompt_handle = u'ViEW .PlAN ::- ENtER hANdlE: '

    redraw()
    echo(u'\r\n\r\n')
    nonstop = False
    row = 10  # after-art,
    for txt in last_callers:
        echo(Ansi(txt).ljust(term.width / 2).center(term.width))
        echo(u'\r\n')
        row += 1
        if ((not nonstop and row > 0 and 0 == (row % (term.height - 3)))
                or (row == len(last_callers) - 1)):
            echo(msg_prompt)
            inp = getch()
            row = 2
            if inp in (u's', u'S', u'q', u'Q', term.KEY_EXIT):
                return
            if inp in (u'v', u'V') or 'sysop' in session.user.groups and (
                    inp in (u'e', u'E')):
                echo(u'\r\n\r\n')
                echo(msg_prompt_handle)
                handle = LineEditor(ini.CFG.getint('nua', 'max_user')).read()
                usrlist = list_users()
                if handle is None or 0 == len(handle.strip()):
                    continue
                handle = handle.strip()
                if handle.lower() in [nick.lower() for nick in list_users()]:
                    nick = ((_nick for _nick in usrlist
                        if _nick.lower() == handle.lower()).next())
                    if find_user(nick):
                        user = get_user(nick)
                        if 'sysop' in session.user.groups and (
                                inp in (u'e', u'E')):
                            gosub('profile', user.handle)
                        else:
                            view_plan(user.handle)
                else:
                    misses = [nick for nick in usrlist.keys()
                              if nick.lower().startswith(handle[:1].lower())]
                    if len(misses) > 0:
                        echo(u'%s:\r\n\r\n%s\r\n' % (msg_partial,
                            Ansi(', '.join(misses)).wrap(term.width)))
                    continue
            if inp in ('n', u'N'):
                nonstop = True
            echo(u'\r\n\r\n')
    pak()