Example #1
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,
        })
Example #2
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,
    })
Example #3
0
def otp_setup(request):
    dev = TOTPDevice.objects.get(user=request.user)
    secret = None
    conf_form = None
    skeys = None

    if request.method == 'POST':
        if 'disable' in request.POST:
            with get_bound_ldapuser(request) as user:
                dev.disable(user)
        elif 'confirm' in request.POST and 'otp_secret' in request.session:
            secret = request.session['otp_secret']
            conf_form = OTPForm(request.POST)
            try:
                if not conf_form.is_valid():
                    raise OkupyError()
                token = conf_form.cleaned_data['otp_token']

                # prevent reusing the same token to login
                if not RevokedToken.add(token, request.user):
                    raise OkupyError()
                if not dev.verify_token(token, secret):
                    raise OkupyError()
            except OkupyError:
                messages.error(request, 'Token verification failed.')
                conf_form = OTPForm()
            else:
                with get_bound_ldapuser(request) as user:
                    dev.enable(user, secret)
                    secret = None
                    conf_form = None
                    sdev = SOTPDevice.objects.get(user=request.user)
                    skeys = sdev.gen_keys(user)
                messages.info(request, 'The new secret has been set.')
        elif 'enable' in request.POST:
            secret = dev.gen_secret()
            request.session['otp_secret'] = secret
            conf_form = OTPForm()
        elif 'recovery' in request.POST:
            sdev = SOTPDevice.objects.get(user=request.user)
            with get_bound_ldapuser(request) as user:
                skeys = sdev.gen_keys(user)
            messages.info(request, 'Your old recovery keys have been revoked.')
        elif 'cancel' in request.POST:
            messages.info(
                request, 'Secret change aborted. Previous settings'
                'are in effect.')

    if secret:
        # into groups of four characters
        secret = ' '.join([secret[i:i + 4] for i in range(0, len(secret), 4)])
    if skeys:
        # xxx xx xxx
        def group_key(s):
            return ' '.join([s[0:3], s[3:5], s[5:8]])

        skeys = list([group_key(k) for k in skeys])

    return render(
        request, 'otp-setup.html', {
            'otp_enabled': dev.is_enabled(),
            'secret': secret,
            'conf_form': conf_form,
            'skeys': skeys,
        })
Example #4
0
def otp_setup(request):
    dev = TOTPDevice.objects.get(user=request.user)
    secret = None
    conf_form = None
    skeys = None

    if request.method == 'POST':
        if 'disable' in request.POST:
            with get_bound_ldapuser(request) as user:
                dev.disable(user)
        elif 'confirm' in request.POST and 'otp_secret' in request.session:
            secret = request.session['otp_secret']
            conf_form = OTPForm(request.POST)
            try:
                if not conf_form.is_valid():
                    raise OkupyError()
                token = conf_form.cleaned_data['otp_token']

                # prevent reusing the same token to login
                if not RevokedToken.add(token, request.user):
                    raise OkupyError()
                if not dev.verify_token(token, secret):
                    raise OkupyError()
            except OkupyError:
                messages.error(request, 'Token verification failed.')
                conf_form = OTPForm()
            else:
                with get_bound_ldapuser(request) as user:
                    dev.enable(user, secret)
                    secret = None
                    conf_form = None
                    sdev = SOTPDevice.objects.get(user=request.user)
                    skeys = sdev.gen_keys(user)
                messages.info(request, 'The new secret has been set.')
        elif 'enable' in request.POST:
            secret = dev.gen_secret()
            request.session['otp_secret'] = secret
            conf_form = OTPForm()
        elif 'recovery' in request.POST:
            sdev = SOTPDevice.objects.get(user=request.user)
            with get_bound_ldapuser(request) as user:
                skeys = sdev.gen_keys(user)
            messages.info(request, 'Your old recovery keys have been revoked.')
        elif 'cancel' in request.POST:
            messages.info(request, 'Secret change aborted. Previous settings'
                          'are in effect.')

    if secret:
        # into groups of four characters
        secret = ' '.join([secret[i:i + 4]
                           for i in range(0, len(secret), 4)])
    if skeys:
        # xxx xx xxx
        def group_key(s):
            return ' '.join([s[0:3], s[3:5], s[5:8]])
        skeys = list([group_key(k) for k in skeys])

    return render(request, 'otp-setup.html', {
        'otp_enabled': dev.is_enabled(),
        'secret': secret,
        'conf_form': conf_form,
        'skeys': skeys,
    })