Compare commits

...

9 Commits
2.0.0 ... 2.0.1

Author SHA1 Message Date
老广
2acc1dc875 Merge pull request #4134 from jumpserver/fix-mfa-1.5
Fix mfa 1.5
2020-06-22 19:05:15 +08:00
xinwen
32ed43ba7b Merge branch 'v2.0' into fix-mfa-1.5 2020-06-22 19:04:42 +08:00
xinwen
3e993fd044 [Update] 调整MFA绑定策略 V2 2020-06-22 19:02:14 +08:00
xinwen
005573b53b [Fix] 重新绑定 MFA 的漏洞 2020-06-22 18:03:45 +08:00
BaiJiangJie
408b2d6dbd Merge pull request #4125 from jumpserver/v2.0_bugfix
v2.0 添加改密计划安全模式配置项
2020-06-20 19:24:17 +08:00
BaiJiangJie
ebc63b9410 Merge pull request #4123 from jumpserver/v1.5_bugfix
[Update] 添加改密计划安全模式配置项
2020-06-20 16:20:53 +08:00
Michael Bai
f1e5c7c2bb 添加改密计划安全模式配置项 2020-06-20 16:18:58 +08:00
Michael Bai
fcb0aefe3c 更改改密计划安全模式配置项名 2020-06-20 15:47:39 +08:00
Bai
29666cc8d3 [Update] 添加改密计划安全模式配置项 2020-06-19 20:41:51 +08:00
6 changed files with 74 additions and 5 deletions

View File

@@ -10,3 +10,7 @@ class HttpResponseTemporaryRedirect(HttpResponse):
def __init__(self, redirect_to):
HttpResponse.__init__(self)
self['Location'] = iri_to_uri(redirect_to)
def get_remote_addr(request):
return request.META.get("HTTP_X_FORWARDED_HOST") or request.META.get("REMOTE_ADDR")

View File

@@ -259,7 +259,8 @@ class Config(dict):
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
'ORG_CHANGE_TO_URL': '',
'LANGUAGE_CODE': 'zh',
'TIME_ZONE': 'Asia/Shanghai'
'TIME_ZONE': 'Asia/Shanghai',
'CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED': True
}
def compatible_auth_openid_of_key(self):

View File

@@ -86,7 +86,11 @@ TASK_LOG_KEEP_DAYS = CONFIG.TASK_LOG_KEEP_DAYS
ORG_CHANGE_TO_URL = CONFIG.ORG_CHANGE_TO_URL
WINDOWS_SKIP_ALL_MANUAL_PASSWORD = CONFIG.WINDOWS_SKIP_ALL_MANUAL_PASSWORD
AUTH_EXPIRED_SECONDS = 60 * 5
# XPACK
XPACK_LICENSE_IS_VALID = DYNAMIC.XPACK_LICENSE_IS_VALID
LOGO_URLS = DYNAMIC.LOGO_URLS
CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED = CONFIG.CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED

View File

@@ -5,8 +5,8 @@ import re
import pyotp
import base64
import logging
import time
from django.http import Http404
from django.conf import settings
from django.utils.translation import ugettext as _
from django.core.cache import cache
@@ -333,3 +333,15 @@ def get_source_choices():
if settings.AUTH_CAS:
choices.append((User.SOURCE_CAS, choices_all[User.SOURCE_CAS]))
return choices
def is_auth_time_valid(session, key):
return True if session.get(key, 0) > time.time() else False
def is_auth_password_time_valid(session):
return is_auth_time_valid(session, 'auth_password_expired_at')
def is_auth_otp_time_valid(session):
return is_auth_time_valid(session, 'auth_opt_expired_at')

View File

@@ -1,4 +1,5 @@
# ~*~ coding: utf-8 ~*~
import time
from django.urls import reverse_lazy, reverse
from django.utils.translation import ugettext as _
@@ -6,13 +7,17 @@ from django.views.generic.base import TemplateView
from django.views.generic.edit import FormView
from django.contrib.auth import logout as auth_logout
from django.conf import settings
from django.http.response import HttpResponseForbidden
from common.utils import get_logger
from authentication.mixins import AuthMixin
from users.models import User
from common.utils import get_logger, get_object_or_none
from common.permissions import IsValidUser
from ... import forms
from .password import UserVerifyPasswordView
from ...utils import (
generate_otp_uri, check_otp_code, get_user_or_pre_auth_user,
is_auth_password_time_valid, is_auth_otp_time_valid
)
__all__ = [
@@ -46,11 +51,50 @@ class UserOtpEnableInstallAppView(TemplateView):
return super().get_context_data(**kwargs)
class UserOtpEnableBindView(TemplateView, FormView):
class UserOtpEnableBindView(AuthMixin, TemplateView, FormView):
template_name = 'users/user_otp_enable_bind.html'
form_class = forms.UserCheckOtpCodeForm
success_url = reverse_lazy('authentication:user-otp-settings-success')
def get(self, request, *args, **kwargs):
if self._check_can_bind():
return super().get(request, *args, **kwargs)
return HttpResponseForbidden()
def post(self, request, *args, **kwargs):
if self._check_can_bind():
return super().post(request, *args, **kwargs)
return HttpResponseForbidden()
def _check_authenticated_user_can_bind(self):
user = self.request.user
session = self.request.session
if not user.mfa_enabled:
return is_auth_password_time_valid(session)
if not user.otp_secret_key:
return is_auth_password_time_valid(session)
return is_auth_otp_time_valid(session)
def _check_unauthenticated_user_can_bind(self):
session_user = None
if not self.request.session.is_empty():
user_id = self.request.session.get('user_id')
session_user = get_object_or_none(User, pk=user_id)
if session_user:
if all((is_auth_password_time_valid(self.request.session), session_user.mfa_enabled, not session_user.otp_secret_key)):
return True
return False
def _check_can_bind(self):
if self.request.user.is_authenticated:
return self._check_authenticated_user_can_bind()
else:
return self._check_unauthenticated_user_can_bind()
def form_valid(self, form):
otp_code = form.cleaned_data.get('otp_code')
otp_secret_key = self.request.session.get('otp_secret_key', '')
@@ -116,6 +160,7 @@ class UserOtpUpdateView(FormView):
valid = user.check_mfa(otp_code)
if valid:
self.request.session['auth_opt_expired_at'] = time.time() + settings.AUTH_EXPIRED_SECONDS
return super().form_valid(form)
else:
error = _('MFA code invalid, or ntp sync server time')

View File

@@ -1,8 +1,10 @@
# ~*~ coding: utf-8 ~*~
import time
from django.conf import settings
from django.contrib.auth import authenticate
from django.shortcuts import redirect
from django.urls import reverse_lazy, reverse
from django.urls import reverse_lazy
from django.utils.translation import ugettext as _
from django.views.generic.edit import UpdateView, FormView
from django.contrib.auth import logout as auth_logout
@@ -76,6 +78,7 @@ class UserVerifyPasswordView(FormView):
user.save()
self.request.session['user_id'] = str(user.id)
self.request.session['auth_password'] = 1
self.request.session['auth_password_expired_at'] = time.time() + settings.AUTH_EXPIRED_SECONDS
return redirect(self.get_success_url())
def get_success_url(self):