Projet

Général

Profil

0007-ppolicy-handle-reset-password-redirection-after-a-ch.patch

Benjamin Renard, 14 novembre 2022 15:36

Télécharger (5,07 ko)

Voir les différences:

Subject: [PATCH 7/7] ppolicy: handle reset password redirection after a
 changeAfterReset error on login

Licence: MIT
 src/authentic2/backends/ldap_backend.py |  9 +++-
 src/authentic2/views.py                 | 10 ++++
 tests/test_ldap.py                      | 68 +++++++++++++++++++++++++
 3 files changed, 86 insertions(+), 1 deletion(-)
src/authentic2/backends/ldap_backend.py
599 599
                message = ' '.join(password_policy_control_messages(c, attributes))
600 600
                if request is not None:
601 601
                    messages.add_message(request, messages.WARNING, message)
602
                    if c.graceAuthNsRemaining or c.timeBeforeExpiration:
602
                    if (
603
                        c.graceAuthNsRemaining
604
                        or c.timeBeforeExpiration
605
                        or (
606
                            c.error is not None
607
                            and ppolicy.PasswordPolicyError.namedValues[c.error] == 'changeAfterReset'
608
                        )
609
                    ):
603 610
                        request.needs_password_change = True
604 611
            else:
605 612
                message = str(vars(c))
src/authentic2/views.py
750 750
                    )
751 751
            elif username:
752 752
                request.journal.record('user.login.failure', username=username)
753

  
754
            if hasattr(request, 'needs_password_change'):
755
                del request.needs_password_change
756
                return utils_misc.redirect(
757
                    request,
758
                    'password_reset',
759
                    resolve=True,
760
                    params={'next': utils_misc.select_next_url(request, '')},
761
                )
762

  
753 763
    context['form'] = form
754 764
    return render(request, 'authentic2/login_password_form.html', context)
755 765

  
tests/test_ldap.py
1439 1439
    assert 'The old password must be supplied.' in response
1440 1440

  
1441 1441

  
1442
def test_login_ppolicy_must_change_password_after_locked(slapd_ppolicy, settings, db, app):
1443
    settings.LDAP_AUTH_SETTINGS = [
1444
        {
1445
            'url': [slapd_ppolicy.ldap_url],
1446
            'basedn': 'o=ôrga',
1447
            'use_tls': False,
1448
            'use_controls': True,
1449
            'can_reset_password': True,
1450
            'ppolicy_dn': 'cn=default,ou=ppolicies,o=ôrga',
1451
        }
1452
    ]
1453

  
1454
    # Add default ppolicy with pwdMaxFailure defined and pwdMustChange enabled
1455
    pwdMaxFailure = 2
1456
    slapd_ppolicy.add_ldif(
1457
        '''
1458
dn: cn=default,ou=ppolicies,o=ôrga
1459
cn: default
1460
objectclass: top
1461
objectclass: device
1462
objectclass: pwdPolicy
1463
objectclass: pwdPolicyChecker
1464
pwdAttribute: userPassword
1465
pwdLockout: TRUE
1466
pwdMaxFailure: {pwdMaxFailure}
1467
pwdMustChange: TRUE
1468
'''.format(
1469
            pwdMaxFailure=pwdMaxFailure
1470
        )
1471
    )
1472

  
1473
    # Locked account after some login errors
1474
    for _ in range(pwdMaxFailure):
1475
        response = app.get('/login/')
1476
        response.form.set('username', USERNAME)
1477
        response.form.set('password', 'invalid')
1478
        response = response.form.submit(name='login-password-submit')
1479
        assert 'Incorrect Username or password' in str(response.pyquery('.errornotice'))
1480
        assert 'account is locked' not in str(response.pyquery('.messages'))
1481
    response = app.get('/login/')
1482
    response.form.set('username', USERNAME)
1483
    response.form.set('password', 'invalid')
1484
    response = response.form.submit(name='login-password-submit')
1485

  
1486
    assert 'account is locked since ' in str(response.pyquery('.messages'))
1487
    assert f'after {pwdMaxFailure} failures' in str(response.pyquery('.messages'))
1488

  
1489
    # Unlock account and force passwor reset
1490
    conn = slapd_ppolicy.get_connection_admin()
1491
    ldif = [
1492
        (ldap.MOD_DELETE, 'pwdAccountLockedTime', None),
1493
        (ldap.MOD_ADD, 'pwdReset', [b'TRUE']),
1494
    ]
1495
    conn.modify_s(DN, ldif)
1496

  
1497
    # Login with the right password
1498
    next_url = '/'
1499
    response = app.get(f'/login/?next={next_url}')
1500
    response.form.set('username', USERNAME)
1501
    response.form.set('password', PASS)
1502
    response = response.form.submit(name='login-password-submit')
1503

  
1504
    assert '/password/reset/' in response['Location']
1505
    assert f'next={next_url}' in response['Location']
1506
    response = response.follow()
1507
    assert 'The password was reset and must be changed.' in str(response.pyquery('.messages'))
1508

  
1509

  
1442 1510
def test_user_change_password_not_allowed(slapd_ppolicy, settings, app, db):
1443 1511
    settings.LDAP_AUTH_SETTINGS = [
1444 1512
        {
1445
-