Exemple #1
0
def verify(session, username, password):
    """Return True if and only if username is in the users DB
    and has correct password."""
    entity = get_user(session, username)
    if entity:
        return Hasher.verify(password, entity.password)
    else:
        return False
Exemple #2
0
def verify(session, username, password):
    """Return True if and only if username is in the users DB
    and has correct password."""
    entity = get_user(session, username)
    if entity:
        return Hasher.verify(password, entity.password)
    else:
        return False
def handle_message_command(message):
    """Handles message broadcast requests."""
    LOG.info('Received message command: message=%r', message)
    try:
        decodedmex = base64.b64decode(message)
    except TypeError:
        LOG.error('Received message is not valid base64: %r', message)
    else:
        text = decodedmex.decode('utf8')
        #FIXME maybe get author ID from message?
        user = "******"
        with session_scope() as session:
            user = query.get_user(session, user)
            if not user:
                LOG.error("Non-existent user %r, not logging message.", user)
                return
            message = query.log_message(session, user, text)
            broadcast(message.jsondict())
        notifier.send_message(text)
Exemple #4
0
    def post(self):
        text = self.get_argument('msgtext')
        username = self.get_current_user()

        text = xhtml_escape(text)

        LOG.info("{} sent message {!r} from web".format(username, text))

        with session_scope() as session:
            user = query.get_user(session, username)
            message = query.log_message(session, user, text)
            LOG.info("Broadcasting to clients")
            broadcast(message.jsondict())
            LOG.info("Notifying Fonera")
            notifier.send_message(text)

        self.render('templates/message.html',
                    message='Messaggio inviato correttamente!',
                    text=text)
    def post(self):
        text = self.get_argument('msgtext')
        username = self.get_current_user()

        LOG.info("%r sent message %r from web", username, text)

        with session_scope() as session:
            user = query.get_user(session, username)
            message = query.log_message(session, user, text)
            LOG.info("Broadcasting to clients")
            broadcast(message.jsondict())
            LOG.info("Notifying Fonera")
            notifier.send_message(text)

        self.render(
            'templates/message.html',
            message='Messaggio inviato correttamente!',
            text=text
        )
Exemple #6
0
def handle_message_command(message):
    """Handles message broadcast requests."""
    LOG.info('Received message command: message={!r}'.format(message))
    try:
        decodedmex = base64.b64decode(message)
    except TypeError:
        LOG.error('Received message is not valid base64: {!r}'.format(message))
    else:
        text = decodedmex.decode('utf8')
        #FIXME maybe get author ID from message?
        user = "******"
        with session_scope() as session:
            user = query.get_user(session, user)
            if not user:
                LOG.error(
                    "Non-existent user {}, not logging message.".format(user))
                return
            message = query.log_message(session, user, text)
            broadcast(message.jsondict())
        notifier.send_message(text)
def verify(session, username, supplied_password, ip_address, has_captcha, recaptcha_challenge, recaptcha_response):
    """Verify user credentials.

    If the username exists, then the supplied password is hashed and
    compared with the stored hash. Otherwise, an hash is calculated and discarded.

    An hash is calculated regardless of the existence of the username, so that
    the response time is approximately the same whether the username exists or not,
    mitigating a timing attack to reveal valid usernames.

    In order to mitigate DoS/bruteforce attacks, two temporal limitations are enforced:

    1. Max 1 failed login attempt per IP address each second (regardless of username)
    2. Max 1 failed login attempt per each username per IP address each
       `min_log_retry` seconds (see bitsd.properties), whether the username
       exists or not.

    A DoS protection is necessary because password hashing is an expensive operation.
    """
    if has_captcha:
        solved_captcha = ReCaptcha.is_solution_correct(recaptcha_response, recaptcha_challenge, ip_address)
        # Exit immediately if wrong answer
        if not solved_captcha:
            return False
    else:
        solved_captcha = False

    # Save "now" so that the two timestamp checks are referred to the same instant
    now = datetime.now()

    def detect_dos(attempt, timeout):
        if solved_captcha:
            return False

        # Otherwise, check timing
        if attempt is not None:
            too_quick = (now - attempt.timestamp) < timeout
            if too_quick:
                log_last_login_attempt(session, ip_address, username)
                return True
            else:
                # Clean up if no more relevant
                session.delete(attempt)
        return False

    last_attempt_for_ip = get_last_login_attempt(session, ip_address)
    last_attempt_for_ip_and_username = get_last_login_attempt(session, ip_address, username)

    if detect_dos(last_attempt_for_ip, timedelta(seconds=1)):
        raise DoSError("Too frequent requests from {}".format(ip_address))

    if detect_dos(last_attempt_for_ip_and_username, timedelta(seconds=options.min_login_retry)):
        raise DoSError("Too frequent attempts from {} for username {}".format(ip_address, username))

    user = get_user(session, username)

    if user is None:
        LOG.warn("Failed attempt for non existent user %r", username)
        # Calculate hash anyway (see docs for the explanation)
        Hasher.encrypt(supplied_password)
        log_last_login_attempt(session, ip_address, username)
        return False
    else:
        valid = Hasher.verify(supplied_password, user.password)
        if not valid:
            log_last_login_attempt(session, ip_address, username)
        return valid
def usermod(session, username, password):
    """"Modify password for existing user."""
    user = get_user(session, username)
    user.password = Hasher.encrypt(password)
    persist(session, user)
def userdel(session, username):
    """Delete user from database."""
    user = get_user(session, username)
    delete(session, user)
Exemple #10
0
def usermod(session, username, password):
    """"Modify password for existing user."""
    user = get_user(session, username)
    user.password = Hasher.encrypt(password)
    persist(session, user)
Exemple #11
0
def userdel(session, username):
    """Delete user from database."""
    user = get_user(session, username)
    delete(session, user)