Exemplo n.º 1
0
 def test_secondary_password_gets_added_in_ldap(self):
     request = set_request(uri='/', user=vars.USER_ALICE)
     self.assertEqual(len(ldap_users('alice')[1]['userPassword']), 1)
     set_secondary_password(request, 'ldaptest')
     self.assertEqual(len(ldap_users(
         'alice',
         directory=self.ldapobj.directory)[1]['userPassword']), 2)
Exemplo n.º 2
0
 def test_session_and_ldap_secondary_passwords_match(self):
     request = set_request(uri='/', user=vars.USER_ALICE)
     set_secondary_password(request, 'ldaptest')
     self.assertTrue(ldap_md5_crypt.verify(b64encode(cipher.decrypt(
         request.session['secondary_password'], 48)),
         ldap_users(
             'alice',
             directory=self.ldapobj.directory)[1]['userPassword'][1]))
Exemplo n.º 3
0
 def test_remove_leftovers_before_adding_secondary_password(self):
     leftover = ldap_md5_crypt.encrypt('leftover_password')
     self.ldapobj.directory[ldap_users('alice')[0]][
         'userPassword'].append(leftover)
     request = set_request(uri='/', user=vars.USER_ALICE)
     set_secondary_password(request, 'ldaptest')
     self.assertNotIn(leftover, ldap_users(
         'alice', directory=self.ldapobj.directory)[1]['userPassword'])
Exemplo n.º 4
0
 def test_dont_remove_primary_password_while_cleaning_leftovers(self):
     leftover = ldap_md5_crypt.encrypt('leftover_password')
     self.ldapobj.directory[ldap_users('alice')[0]][
         'userPassword'].append(leftover)
     request = set_request(uri='/', user=vars.USER_ALICE)
     set_secondary_password(request, 'ldaptest')
     self.assertTrue(ldap_md5_crypt.verify(
         'ldaptest', ldap_users(
             'alice',
             directory=self.ldapobj.directory)[1]['userPassword'][0]))
Exemplo n.º 5
0
 def test_dont_remove_unknown_hashes_while_cleaning_leftovers(self):
     leftover = ldap_md5_crypt.encrypt('leftover_password')
     self.ldapobj.directory[ldap_users('alice')[0]][
         'userPassword'].append(leftover)
     leftover2 = 'plain_leftover2'
     self.ldapobj.directory[ldap_users('alice')[0]][
         'userPassword'].append(leftover2)
     request = set_request(uri='/', user=vars.USER_ALICE)
     set_secondary_password(request, 'ldaptest')
     self.assertIn(leftover2, ldap_users(
         'alice', directory=self.ldapobj.directory)[1]['userPassword'])
Exemplo n.º 6
0
def login(request):
    """ The login page """
    user = None
    oreq = request.session.get('openid_request', None)
    # this can be POST or GET, and can be null or empty
    next = request.REQUEST.get('next') or reverse(index)
    is_otp = False
    login_form = None
    strong_auth_req = 'strong_auth_requested' in request.session

    if oreq:
        login_form_class = OpenIDLoginForm
    elif ('strong_auth_requested' in request.session
          and request.user.is_authenticated()):
        login_form_class = StrongAuthForm
    else:
        login_form_class = LoginForm

    try:
        if request.method != 'POST':
            pass
        elif 'cancel' in request.POST:
            # note: this wipes request.session
            _logout(request)
            if oreq is not None:
                oresp = oreq.answer(False)
                return render_openid_response(request, oresp)
        elif 'otp_token' in request.POST:
            # if user's not authenticated, go back to square one
            if not request.user.is_authenticated():
                raise OkupyError('OTP verification timed out')

            is_otp = True
            otp_form = OTPForm(request.POST)
            if otp_form.is_valid():
                token = otp_form.cleaned_data['otp_token']
            else:
                raise OkupyError('OTP verification failed')

            # prevent replay attacks and race conditions
            if not RevokedToken.add(token, request.user):
                raise OkupyError('OTP verification failed')
            dev = django_otp.match_token(request.user, token)
            if not dev:
                raise OkupyError('OTP verification failed')
            django_otp.login(request, dev)
        else:
            login_form = login_form_class(request.POST)
            if login_form.is_valid():
                if login_form_class != StrongAuthForm:
                    username = login_form.cleaned_data['username']
                else:
                    username = request.user.username
                password = login_form.cleaned_data['password']
            else:
                raise OkupyError('Login failed')
            """
            Perform authentication, if it retrieves a user object then
            it was successful. If it retrieves None then it failed to login
            """
            try:
                user = authenticate(request=request,
                                    username=username,
                                    password=password)
            except Exception as error:
                logger.critical(error, extra=log_extra_data(request))
                logger_mail.exception(error)
                raise OkupyError(
                    "Can't contact the LDAP server or the database")
            if not user:
                raise OkupyError('Login failed')

            if oreq:
                request.session['auto_logout'] = (
                    login_form.cleaned_data['auto_logout'])
    except OkupyError as error:
        messages.error(request, str(error))

    if user and user.is_active:
        _login(request, user)
        # prepare devices, and see if OTP is enabled
        init_otp(request)
        set_secondary_password(request=request, password=password)
    if request.user.is_authenticated():
        if (strong_auth_req and not 'secondary_password' in request.session):
            if request.method != 'POST':
                messages.info(
                    request, 'You need to type in your password' +
                    ' again to perform this action')
        else:
            if request.user.is_verified():
                return redirect(next)
            login_form = OTPForm()
            is_otp = True
    if login_form is None:
        login_form = login_form_class()

    if is_otp or strong_auth_req:
        ssl_auth_form = None
        ssl_auth_uri = None
        ssh_auth_command = None
    else:
        encrypted_id = sessionrefcipher.encrypt(request.session)

        # TODO: it fails when:
        # 1. site is accessed via IP (auth.127.0.0.1),
        # 2. HTTP used on non-standard port (https://...:8000).
        ssl_auth_form = SSLCertLoginForm({
            'session':
            encrypted_id,
            'next':
            request.build_absolute_uri(next),
            'login_uri':
            request.build_absolute_uri(request.get_full_path()),
        })

        ssl_auth_host = 'auth.' + request.get_host()
        ssl_auth_path = reverse(ssl_auth)
        ssl_auth_uri = urljoin('https://' + ssl_auth_host, ssl_auth_path)

        if settings.SSH_BIND[1] == 22:
            ssh_port_opt = ''
        else:
            ssh_port_opt = '-p %d ' % settings.SSH_BIND[1]

        ssh_auth_command = 'ssh %sauth+%s@%s' % (
            ssh_port_opt, encrypted_id, request.get_host().split(':')[0])

    return render(
        request, 'login.html', {
            'login_form': login_form,
            'openid_request': oreq,
            'next': next,
            'ssl_auth_uri': ssl_auth_uri,
            'ssl_auth_form': ssl_auth_form,
            'ssh_auth_command': ssh_auth_command,
            'is_otp': is_otp,
        })
Exemplo n.º 7
0
 def test_secondary_password_gets_added_in_session(self):
     request = set_request(uri='/', user=vars.USER_ALICE)
     set_secondary_password(request, 'ldaptest')
     self.assertEqual(len(request.session['secondary_password']), 48)
Exemplo n.º 8
0
def login(request):
    """ The login page """
    user = None
    oreq = request.session.get('openid_request', None)
    # this can be POST or GET, and can be null or empty
    next = request.REQUEST.get('next') or reverse(index)
    is_otp = False
    login_form = None
    strong_auth_req = 'strong_auth_requested' in request.session

    if oreq:
        login_form_class = OpenIDLoginForm
    elif ('strong_auth_requested' in request.session
            and request.user.is_authenticated()):
        login_form_class = StrongAuthForm
    else:
        login_form_class = LoginForm

    try:
        if request.method != 'POST':
            pass
        elif 'cancel' in request.POST:
            # note: this wipes request.session
            _logout(request)
            if oreq is not None:
                oresp = oreq.answer(False)
                return render_openid_response(request, oresp)
        elif 'otp_token' in request.POST:
            # if user's not authenticated, go back to square one
            if not request.user.is_authenticated():
                raise OkupyError('OTP verification timed out')

            is_otp = True
            otp_form = OTPForm(request.POST)
            if otp_form.is_valid():
                token = otp_form.cleaned_data['otp_token']
            else:
                raise OkupyError('OTP verification failed')

            # prevent replay attacks and race conditions
            if not RevokedToken.add(token, request.user):
                raise OkupyError('OTP verification failed')
            dev = django_otp.match_token(request.user, token)
            if not dev:
                raise OkupyError('OTP verification failed')
            django_otp.login(request, dev)
        else:
            login_form = login_form_class(request.POST)
            if login_form.is_valid():
                if login_form_class != StrongAuthForm:
                    username = login_form.cleaned_data['username']
                else:
                    username = request.user.username
                password = login_form.cleaned_data['password']
            else:
                raise OkupyError('Login failed')
            """
            Perform authentication, if it retrieves a user object then
            it was successful. If it retrieves None then it failed to login
            """
            try:
                user = authenticate(
                    request=request,
                    username=username,
                    password=password)
            except Exception as error:
                logger.critical(error, extra=log_extra_data(request))
                logger_mail.exception(error)
                raise OkupyError(
                    "Can't contact the LDAP server or the database")
            if not user:
                raise OkupyError('Login failed')

            if oreq:
                request.session['auto_logout'] = (
                    login_form.cleaned_data['auto_logout'])
    except OkupyError as error:
        messages.error(request, str(error))

    if user and user.is_active:
        _login(request, user)
        # prepare devices, and see if OTP is enabled
        init_otp(request)
        set_secondary_password(request=request, password=password)
    if request.user.is_authenticated():
        if (strong_auth_req
                and not 'secondary_password' in request.session):
            if request.method != 'POST':
                messages.info(request, 'You need to type in your password'
                              + ' again to perform this action')
        else:
            if request.user.is_verified():
                return redirect(next)
            login_form = OTPForm()
            is_otp = True
    if login_form is None:
        login_form = login_form_class()

    if is_otp or strong_auth_req:
        ssl_auth_form = None
        ssl_auth_uri = None
        ssh_auth_command = None
    else:
        encrypted_id = sessionrefcipher.encrypt(request.session)

        # TODO: it fails when:
        # 1. site is accessed via IP (auth.127.0.0.1),
        # 2. HTTP used on non-standard port (https://...:8000).
        ssl_auth_form = SSLCertLoginForm({
            'session': encrypted_id,
            'next': request.build_absolute_uri(next),
            'login_uri': request.build_absolute_uri(request.get_full_path()),
        })

        ssl_auth_host = 'auth.' + request.get_host()
        ssl_auth_path = reverse(ssl_auth)
        ssl_auth_uri = urljoin('https://' + ssl_auth_host, ssl_auth_path)

        if settings.SSH_BIND[1] == 22:
            ssh_port_opt = ''
        else:
            ssh_port_opt = '-p %d ' % settings.SSH_BIND[1]

        ssh_auth_command = 'ssh %sauth+%s@%s' % (
            ssh_port_opt,
            encrypted_id,
            request.get_host().split(':')[0])

    return render(request, 'login.html', {
        'login_form': login_form,
        'openid_request': oreq,
        'next': next,
        'ssl_auth_uri': ssl_auth_uri,
        'ssl_auth_form': ssl_auth_form,
        'ssh_auth_command': ssh_auth_command,
        'is_otp': is_otp,
    })