Fixed wrong way to check for passwords using deprecated scheme.

see #3350
This commit is contained in:
Antoine Nguyen
2024-11-29 17:04:48 +01:00
parent 4b64d5e435
commit 27dbd71a60
10 changed files with 62 additions and 25 deletions
+1 -1
View File
@@ -168,7 +168,7 @@ Update your :file:`settings.py` file with following content:
"ckeditor.W001", # CKEditor 4.22.1 warning
]
This will silence a `warning sent by django-ckeditor <https://github.com/modoboa/modoboa/issues/3316>_`.
This will silence a `warning sent by django-ckeditor <https://github.com/modoboa/modoboa/issues/3316>`_.
Version 2.3.0
=============
+19 -1
View File
@@ -23,7 +23,7 @@
'The password scheme you are using has been deprecated and will be removed in the next minor version. The procedure to upgrade to a stronger scheme is as follows:'
)
}}
<ol>
<ol class="mt-4">
<li
v-html="
$gettext(
@@ -65,6 +65,24 @@
"
></li>
</ol>
<p
class="mt-4"
v-html="
$gettext(
'You must apply this procedure <strong>BEFORE</strong> you install a newest version of Modoboa, otherwise <strong>you will be unable to connect to the web interface anymore</strong>.',
true
)
"
></p>
<p
class="mt-4"
v-html="
$gettext(
'Please note that you will see this message until <strong>ALL</strong> user passwords have been converted using the new scheme.',
true
)
"
></p>
</template>
</v-alert>
</v-card-text>
+6 -5
View File
@@ -2,9 +2,10 @@ from django.core.checks import register, Info, Warning
from django.conf import settings
from django.utils.translation import gettext as _
from modoboa.core.models import User
from modoboa.core.password_hashers import get_configured_password_hasher
from modoboa.core.utils import generate_rsa_private_key
from modoboa.core.utils import (
check_for_deprecated_password_schemes,
generate_rsa_private_key,
)
W001 = Warning(
_(
@@ -49,7 +50,7 @@ def check_rsa_private_key_exists(app_configs, **kwargs):
@register()
def check_password_hasher(app_configs, **kwargs):
msgs = []
hasher = get_configured_password_hasher()
if hasher.deprecated or User.objects.is_password_scheme_in_use(hasher):
hasher = check_for_deprecated_password_schemes()
if hasher:
msgs.append(W002)
return msgs
+4 -4
View File
@@ -12,7 +12,7 @@ from django.urls import reverse
from django.utils.encoding import smart_str
from django.utils.translation import gettext as _
from modoboa.core.password_hashers import get_configured_password_hasher
from modoboa.core.utils import check_for_deprecated_password_schemes
from modoboa.lib import exceptions, permissions
from modoboa.lib.signals import get_request
from . import models, signals as core_signals, utils
@@ -132,13 +132,13 @@ def check_for_new_versions(sender, include_all: bool, **kwargs) -> list:
]
elif include_all:
result += [{"id": "newversionavailable"}]
hasher = get_configured_password_hasher()
if hasher.deprecated or models.User.objects.is_password_scheme_in_use(hasher):
hasher = check_for_deprecated_password_schemes()
if hasher:
result += [
{
"id": "deprecatedpasswordscheme",
"url": reverse("core:index") + "#info/",
"text": _("You are using a deprecated password scheme (%s)")
"text": _("You are still using a deprecated password scheme (%s)")
% hasher.name,
"level": "warning",
}
+1 -1
View File
@@ -44,7 +44,7 @@ def get_default_language() -> str:
class UserManager(BaseUserManager):
"""Custom manager for User."""
def is_password_scheme_in_use(self, password_hasher: PasswordHasher) -> bool:
def is_password_scheme_in_use(self, password_hasher: type[PasswordHasher]) -> bool:
"""Check if given password scheme is still in use."""
return (
self.get_queryset()
+2 -2
View File
@@ -18,7 +18,7 @@ from modoboa.core.password_hashers.base import ( # NOQA:F401
from modoboa.parameters import tools as param_tools
def get_password_hasher(scheme: str) -> PasswordHasher:
def get_password_hasher(scheme: str) -> type[PasswordHasher]:
"""Retrieve the hasher corresponding to :keyword:`scheme`.
If no class is found, `PLAINHasher` is returned.
@@ -35,7 +35,7 @@ def get_password_hasher(scheme: str) -> PasswordHasher:
return hasher
def get_configured_password_hasher() -> PasswordHasher:
def get_configured_password_hasher() -> type[PasswordHasher]:
"""Retrieve the password hasher class currently configured."""
scheme = param_tools.get_global_parameter("password_scheme")
return get_password_hasher(scheme)
+6 -1
View File
@@ -104,10 +104,15 @@ class PasswordHasher(metaclass=MetaHasher):
return False
@classmethod
def get_password_hashers(cls):
def get_password_hashers(cls) -> list[type["PasswordHasher"]]:
"""Return all the PasswordHasher supported by Modoboa"""
return [hasher for hasher in cls.__subclasses__()]
@classmethod
def get_deprecated_password_hashers(cls) -> list[type["PasswordHasher"]]:
"""Return all the PasswordHasher supported by Modoboa and marked as deprecated."""
return [hasher for hasher in cls.__subclasses__() if hasher.deprecated]
class PLAINHasher(PasswordHasher):
"""
+2 -1
View File
@@ -1,6 +1,6 @@
{% load i18n core_tags lib_tags %}
<h2>{% trans "Information" %} <small>{% trans "Various information about Modoboa" %}</small></h2><hr>
{% if password_hasher.deprecated or password_hasher_in_use %}
{% if password_hasher %}
<div class="alert alert-block alert-warning">
<h4>{% trans "You are using a deprecated password scheme!" %}</h4>
<p>{% blocktranslate trimmed %}
@@ -20,6 +20,7 @@
version of Modoboa, otherwise <strong>you will be unable to connect to
the web interface anymore</strong>.
{% endblocktranslate %}</p>
<p>{% blocktranslate trimmed %}Please note that you will see this message until <strong>ALL</strong> user passwords have been converted using the new scheme.{% endblocktranslate %}</p>
</div>
{% endif %}
{% if update_avail %}
+17 -2
View File
@@ -1,15 +1,18 @@
"""Utility functions."""
from pkg_resources import parse_version
import os
import environ
import os
from pkg_resources import parse_version
from typing import Optional
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from django.utils.translation import gettext as _
from modoboa.core import models
from modoboa.core.extensions import exts_pool
from modoboa.core.password_hashers import get_configured_password_hasher, PasswordHasher
from modoboa.lib.api_client import ModoAPIClient
@@ -85,3 +88,15 @@ def generate_rsa_private_key(storage_path: str) -> bool:
with open(env_path, "wb") as fp:
fp.write(b'OIDC_RSA_PRIVATE_KEY="' + content + b'"\n')
return True
def check_for_deprecated_password_schemes() -> Optional[type[PasswordHasher]]:
"""Check if deprecated password scheme is still in use."""
hasher = get_configured_password_hasher()
if hasher.deprecated:
return hasher
deprecated_hashers = PasswordHasher.get_deprecated_password_hashers()
for dhasher in deprecated_hashers:
if models.User.objects.is_password_scheme_in_use(dhasher):
return dhasher
return None
+4 -7
View File
@@ -7,9 +7,8 @@ from django.shortcuts import render
from django.template.loader import render_to_string
from django.utils.translation import gettext as _
from modoboa.core.models import Log, User
from modoboa.core.password_hashers import get_configured_password_hasher
from modoboa.core.utils import check_for_updates
from modoboa.core.models import Log
from modoboa.core.utils import check_for_updates, check_for_deprecated_password_schemes
from modoboa.lib.listing import get_listing_page, get_sort_order
from modoboa.lib.web_utils import render_to_json_response
from modoboa.parameters import tools as param_tools
@@ -61,8 +60,7 @@ def parameters(request, tplname="core/parameters.html"):
@user_passes_test(lambda u: u.is_superuser)
def information(request, tplname="core/information.html"):
status, extensions = check_for_updates()
hasher = get_configured_password_hasher()
password_hasher_in_use = User.objects.is_password_scheme_in_use(hasher)
hasher = check_for_deprecated_password_schemes()
return render_to_json_response(
{
"content": render_to_string(
@@ -71,8 +69,7 @@ def information(request, tplname="core/information.html"):
"update_avail": status,
"extensions": extensions,
"password_hasher": hasher,
"password_hasher_in_use": password_hasher_in_use,
"scheme": hasher.name,
"scheme": hasher.name if hasher else "",
},
),
}