Skip to content

Commit

Permalink
Make the crypt module optional. Fix #67
Browse files Browse the repository at this point in the history
The python stdlid crypt module is deprecated since version 3.11 and
will be removed in version 3.13. Check for the availability of the
crypt module.
All password checks using the crypt module will stop to work on
python 3.13.
  • Loading branch information
nitmir committed Aug 18, 2024
1 parent 437fdd0 commit 30f2358
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@ Added
* Support for Django 4.2
* Allow forms to be overridden from settings

Deprecated
----------

* Make the crypt module optional and deprecate it's usage.
The python stdlid crypt module is deprecated since version 3.11 and
will be removed in version 3.13. Check for the availability of the
crypt module.
All password checks using the crypt module will stop to work on
python 3.13.


v2.0.0 - 2022-10-17
===================
Expand Down
20 changes: 12 additions & 8 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -383,16 +383,17 @@ Only useful if you are using the mysql authentication backend:
* ``CAS_SQL_PASSWORD_CHECK``: The method used to check the user password. Must be one of the following:

* ``"crypt"`` (see <https://en.wikipedia.org/wiki/Crypt_(C)>), the password in the database
should begin with $
should begin with $. This method is deprecated and will stop to work in python 3.13.
* ``"ldap"`` (see https://tools.ietf.org/id/draft-stroeder-hashed-userpassword-values-01.html)
the password in the database must begin with one of {MD5}, {SMD5}, {SHA}, {SSHA}, {SHA256},
{SSHA256}, {SHA384}, {SSHA384}, {SHA512}, {SSHA512}, {CRYPT}.
{SSHA256}, {SHA384}, {SSHA384}, {SHA512}, {SSHA512}, {CRYPT}. {CRYPT} is deprecated
and will stop to work in python 3.13.
* ``"hex_HASH_NAME"`` with ``HASH_NAME`` in md5, sha1, sha224, sha256, sha384, sha512.
The hashed password in the database is compared to the hexadecimal digest of the clear
password hashed with the corresponding algorithm.
* ``"plain"``, the password in the database must be in clear.

The default is ``"crypt"``.
The default is ``"crypt"``. This default is deprecated and will stop to work in python 3.13.


Sql backend settings
Expand All @@ -409,16 +410,18 @@ used by the sql backend.
* ``CAS_SQL_PASSWORD_CHECK``: The method used to check the user password. Must be one of the following:

* ``"crypt"`` (see <https://en.wikipedia.org/wiki/Crypt_(C)>), the password in the database
should begin with $
should begin with $. This method is deprecated and will stop to work in python 3.13.
* ``"ldap"`` (see https://tools.ietf.org/id/draft-stroeder-hashed-userpassword-values-01.html)
the password in the database must begin with one of {MD5}, {SMD5}, {SHA}, {SSHA}, {SHA256},
{SSHA256}, {SHA384}, {SSHA384}, {SHA512}, {SSHA512}, {CRYPT}.
{SSHA256}, {SHA384}, {SSHA384}, {SHA512}, {SSHA512}, {CRYPT}. {CRYPT} is deprecated
and will stop to work in python 3.13.
* ``"hex_HASH_NAME"`` with ``HASH_NAME`` in md5, sha1, sha224, sha256, sha384, sha512.
The hashed password in the database is compared to the hexadecimal digest of the clear
password hashed with the corresponding algorithm.
* ``"plain"``, the password in the database must be in clear.

The default is ``"crypt"``.
The default is ``"crypt"``. This default is deprecated and will stop to work in python 3.13.

* ``CAS_SQL_PASSWORD_CHARSET``: Charset the SQL users passwords was hash with. This is needed to
encode the user submitted password before hashing it for comparison. The default is ``"utf-8"``.

Expand All @@ -439,10 +442,11 @@ Only useful if you are using the ldap authentication backend:
* ``CAS_LDAP_PASSWORD_CHECK``: The method used to check the user password. Must be one of the following:

* ``"crypt"`` (see <https://en.wikipedia.org/wiki/Crypt_(C)>), the password in the database
should begin with $
should begin with $. This method is deprecated and will stop to work in python 3.13.
* ``"ldap"`` (see https://tools.ietf.org/id/draft-stroeder-hashed-userpassword-values-01.html)
the password in the database must begin with one of {MD5}, {SMD5}, {SHA}, {SSHA}, {SHA256},
{SSHA256}, {SHA384}, {SSHA384}, {SHA512}, {SSHA512}, {CRYPT}.
{SSHA256}, {SHA384}, {SSHA384}, {SHA512}, {SSHA512}, {CRYPT}. {CRYPT} is deprecated and
will stop to work in python 3.13.
* ``"hex_HASH_NAME"`` with ``HASH_NAME`` in md5, sha1, sha224, sha256, sha384, sha512.
The hashed password in the database is compared to the hexadecimal digest of the clear
password hashed with the corresponding algorithm.
Expand Down
3 changes: 3 additions & 0 deletions cas_server/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ def test_plain_unicode(self):

def test_crypt(self):
"""test the crypt auth method"""
# Only run test if crypt is available
if utils.crypt is None:
return
salts = ["$6$UVVAQvrMyXMF3FF3", "aa"]
hashed_password1 = []
for salt in salts:
Expand Down
12 changes: 11 additions & 1 deletion cas_server/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,17 @@
import string
import json
import hashlib
import crypt
import base64
import six
import requests
import time
import logging
import binascii
# The crypt module is deprecated and will be removed in version 3.13
try:
import crypt
except ImportError:
crypt = None

from importlib import import_module
from datetime import datetime, timedelta
Expand Down Expand Up @@ -411,6 +415,8 @@ def crypt_salt_is_valid(salt):
:return: ``True`` if ``salt`` is a valid crypt salt on this system, ``False`` otherwise
:rtype: bool
"""
if crypt is None:
return False
if len(salt) < 2:
return False
else:
Expand Down Expand Up @@ -567,6 +573,8 @@ def hash(cls, scheme, password, salt=None, charset="utf8"):
cls._schemes_to_hash[scheme](password + salt).digest() + salt
)
except KeyError:
if crypt is None:
raise cls.BadScheme("Crypt is not available on the system")
if six.PY3:
password = password.decode(charset)
salt = salt.decode(charset)
Expand Down Expand Up @@ -646,6 +654,8 @@ def check_password(method, password, hashed_password, charset):
if method == "plain":
return password == hashed_password
elif method == "crypt":
if crypt is None:
raise ValueError("Crypt is not available on the system")
if hashed_password.startswith(b'$'):
salt = b'$'.join(hashed_password.split(b'$', 3)[:-1])
elif hashed_password.startswith(b'_'): # pragma: no cover old BSD format not supported
Expand Down

0 comments on commit 30f2358

Please sign in to comment.