예제 #1
0
파일: test_ipa.py 프로젝트: odra/securitas
def test_ipa_untouched_client(client):
    with client.session_transaction() as sess:
        ipa = untouched_ipa_client(current_app)
        assert ipa is not None
        assert 'securitas_session' not in sess
        assert 'securitas_ipa_server_hostname' not in sess
        assert 'securitas_username' not in sess
예제 #2
0
파일: password.py 프로젝트: odra/securitas
def _validate_change_pw_form(form, username, ipa=None):
    if ipa is None:
        ipa = untouched_ipa_client(app)

    current_password = form.current_password.data
    password = form.password.data

    res = None
    try:
        res = ipa.change_password(username, password, current_password)
    except python_freeipa.exceptions.PWChangeInvalidPassword:
        form.current_password.errors.append(
            "The old password or username is not correct")
    except python_freeipa.exceptions.PWChangePolicyError as e:
        form.password.errors.append(e.policy_error)
    except python_freeipa.exceptions.FreeIPAError as e:
        # If we made it here, we hit something weird not caught above. We didn't
        # bomb out, but we don't have IPA creds, either.
        app.logger.error(
            f'An unhandled error {e.__class__.__name__} happened while reseting '
            f'the password for user {username}: {e.message}')
        form.errors['non_field_errors'] = ['Could not change password.']

    if res and res.ok:
        flash('Your password has been changed', 'success')
        app.logger.info(f'Password for {username} was changed')
    return res
예제 #3
0
def password_reset():
    if request.method == 'GET':
        return render_template('password-reset.html')

    username = request.form.get('username')
    current_password = request.form.get('current_password')
    password = request.form.get('password')
    password_confirm = request.form.get('password_confirm')

    if not all([username, current_password, password, password_confirm]):
        flash('Please fill in all fields to reset your password', 'red')
        return redirect(url_for('password_reset'))

    if password != password_confirm:
        flash('Password and confirmation did not match.', 'red')
        return redirect(url_for('password_reset'))

    ipa = untouched_ipa_client(app)
    res = None
    try:
        res = ipa.change_password(username, password, current_password)
    except python_freeipa.exceptions.PWChangePolicyError as e:
        flash(
            'Failed to reset your password (policy error): %s' % str(e.policy_error),
            'red')
        return redirect(url_for('password_reset'))
    except python_freeipa.exceptions.PWChangeInvalidPassword:
        flash(
            'Failed to reset your password (invalid current password).',
            'red')
        return redirect(url_for('password_reset'))
    except python_freeipa.exceptions.FreeIPAError as e:
        flash('Failed to reset your password: %s' % str(e), 'red')
        return redirect(url_for('password_reset'))

    if res and res.ok:
        flash('Your password has been changed, ' \
              'please try to log in with the new one now.',
              'green')
        return redirect(url_for('root'))

    # If we made it here, we hit something weird not caught above. We didn't
    # bomb out, but we don't have a valid/good response from IPA. Boot the user
    # back to /.
    flash('Something went wrong and your password might not have been ' \
          'changed. Please try again, or report the issue to the system ' \
          'administrator.',
          'red')
    return redirect(url_for('root'))
예제 #4
0
파일: conftest.py 프로젝트: odra/securitas
 def _make_user(name):
     now = datetime.datetime.utcnow().replace(microsecond=0)
     password = f'{name}_password'
     ipa_admin.user_add(
         name,
         name.title(),
         'User',
         f'{name.title()} User',
         user_password=password,
         login_shell='/bin/bash',
         fascreationtime=f"{now.isoformat()}Z",
     )
     ipa = untouched_ipa_client(app)
     ipa.change_password(name, password, password)
     created_users.append(name)
예제 #5
0
def register():
    first_name = request.form.get('first_name')
    last_name = request.form.get('last_name')
    username = request.form.get('username')
    password = request.form.get('password')
    password_confirm = request.form.get('password_confirm')

    if not all([first_name, last_name, username, password, password_confirm]):
        flash('Please fill in all fields to register an account.', 'red')
        return redirect(url_for('root'))

    if password != password_confirm:
        flash('Password and confirmation did not match.', 'red')
        return redirect(url_for('root'))

    try:
        ipa_admin.user_add(
            username,
            first_name,
            last_name,
            '%s %s' % (first_name, last_name), # TODO ???
            user_password=password,
            login_shell='/bin/bash')

        # Now we fake a password change, so that it's not immediately expired.
        # This also logs the user in right away.
        ipa = untouched_ipa_client(app)
        ipa.change_password(username, password, password)
    except python_freeipa.exceptions.FreeIPAError as e:
        print(e)
        flash(
            'An error occurred while creating the account, please try again.',
            'red')
        return redirect(url_for('root'))

    flash(
        'Congratulations, you now have an account! Go ahead and sign in to ' \
        'proceed.',
        'green')

    return redirect(url_for('root'))
예제 #6
0
def test_change_recent_password_change(
    client,
    dummy_user,
    dummy_group,
    token_for_dummy_user,
    no_password_min_time,
    patched_lock_active,
):
    ipa_admin.group_add_member("dummy-group", users="dummy")
    ipa = untouched_ipa_client(current_app)
    ipa.change_password("dummy", "dummy_password", "dummy_password")
    result = client.get(f'/forgot-password/change?token={token_for_dummy_user}')
    patched_lock_active["delete"].assert_called_once()
    assert_redirects_with_flash(
        result,
        expected_url="/forgot-password/ask",
        expected_message=(
            "Your password has been changed since you requested this token, please "
            "request a new one."
        ),
        expected_category="warning",
    )
예제 #7
0
def register():
    form = RegisterUserForm()

    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        now = datetime.datetime.utcnow().replace(microsecond=0)
        # First, create the user.
        try:
            ipa_admin.user_add(
                username,
                form.firstname.data,
                form.lastname.data,
                f'{form.firstname.data} {form.lastname.data}',  # TODO ???
                user_password=password,
                login_shell='/bin/bash',
                fascreationtime=f"{now.isoformat()}Z",
                faslocale=guess_locale(),
                fastimezone=app.config["USER_DEFAULTS"]["user_timezone"],
            )
        except python_freeipa.exceptions.DuplicateEntry as e:
            # the username already exists
            form.username.errors.append(e.message)
        except python_freeipa.exceptions.ValidationError as e:
            # for example: invalid username. We don't know which field to link it to
            if e.message.startswith("invalid 'login': "******"invalid 'login': ") :])
            else:
                app.logger.error(
                    f'An unhandled invalid value happened while registering user '
                    f'{username}: {e.message}'
                )
                form.errors['non_field_errors'] = [e.message]
        except python_freeipa.exceptions.FreeIPAError as e:
            app.logger.error(
                f'An unhandled error {e.__class__.__name__} happened while registering user '
                f'{username}: {e.message}'
            )
            form.errors['non_field_errors'] = [
                'An error occurred while creating the account, please try again.'
            ]

        else:
            # User creation succeeded. Now we fake a password change, so that it's not immediately
            # expired. This also logs the user in right away.
            try:
                ipa = untouched_ipa_client(app)
                ipa.change_password(username, password, password)
            except python_freeipa.exceptions.PWChangePolicyError as e:
                # The user is created but the password does not match the policy. Alert the user
                # and ask them to change their password.
                flash(
                    f'Your account has been created, but the password you chose does not comply '
                    f'with the policy ({e.policy_error}) and has thus been set as expired. '
                    f'You will be asked to change it after logging in.',
                    'warning',
                )
                # Send them to the login page, they will have to change their password
                # after login.
                return redirect(url_for('login'))
            except python_freeipa.exceptions.FreeIPAError as e:
                app.logger.error(
                    f'An unhandled error {e.__class__.__name__} happened while changing initial '
                    f'password for user {username}: {e.message}'
                )
                # At this point the user has been created, they can't register again. Send them to
                # the login page with an appropriate warning.
                flash(
                    f'Your account has been created, but an error occurred while setting your '
                    f'password ({e.message}). You may need to change it after logging in.',
                    'warning',
                )
                return redirect(url_for('login'))
            else:
                flash(
                    'Congratulations, you now have an account! Go ahead and sign in to proceed.',
                    'success',
                )
                return redirect(url_for('root'))

    return render_template('register.html', register_form=form)
예제 #8
0
파일: password.py 프로젝트: odra/securitas
def forgot_password_change():
    token = request.args.get('token')
    if not token:
        flash('No token provided, please request one.', 'warning')
        return redirect(url_for('forgot_password_ask'))
    try:
        token_data = jwt.decode(token,
                                app.config["SECRET_KEY"],
                                algorithms=["HS256"])
    except jwt.exceptions.DecodeError:
        flash("The token is invalid, please request a new one.", "warning")
        return redirect(url_for('forgot_password_ask'))
    username = token_data["username"]
    lock = PasswordResetLock(username)
    valid_until = lock.valid_until()
    now = datetime.datetime.now()
    if valid_until is None or now > valid_until:
        lock.delete()
        flash("The token has expired, please request a new one.", "warning")
        return redirect(url_for('forgot_password_ask'))
    user = ipa_admin.user_show(username)
    if user["krblastpwdchange"] != token_data["last_change"]:
        lock.delete()
        flash(
            "Your password has been changed since you requested this token, please request "
            "a new one.",
            "warning",
        )
        return redirect(url_for('forgot_password_ask'))

    form = NewPasswordForm()
    if form.validate_on_submit():
        password = form.password.data
        try:
            ipa_admin.user_mod(username, userpassword=password)
            # Change the password as the user, so it's not expired.
            ipa = untouched_ipa_client(app)
            ipa.change_password(username, password, password)
        except python_freeipa.exceptions.PWChangePolicyError as e:
            lock.delete()
            flash(
                f'Your password has been changed, but it does not comply with '
                f'the policy ({e.policy_error}) and has thus been set as expired. '
                f'You will be asked to change it after logging in.',
                'warning',
            )
            app.logger.info(
                f"Password for {username} was changed to a non-compliant password after "
                f"completing the forgotten password process.")
            # Send them to the login page, they will have to change their password
            # after login.
            return redirect(url_for('login'))
        except python_freeipa.exceptions.FreeIPAError as e:
            # If we made it here, we hit something weird not caught above.
            app.logger.error(
                f'An unhandled error {e.__class__.__name__} happened while reseting '
                f'the password for user {username}: {e.message}')
            form.errors['non_field_errors'] = [
                'Could not change password, please try again.'
            ]
        else:
            lock.delete()
            flash('Your password has been changed.', 'success')
            app.logger.info(
                f"Password for {username} was changed after completing the forgotten "
                f"password process.")
            return redirect(url_for('root'))
    return render_template('forgot-password-change.html',
                           username=username,
                           form=form,
                           token=token)