diff options
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | debian/vyos-1x.postinst | 14 | ||||
-rw-r--r-- | python/vyos/utils/auth.py | 64 | ||||
-rw-r--r-- | smoketest/scripts/cli/base_vyostest_shim.py | 6 | ||||
-rwxr-xr-x | smoketest/scripts/cli/test_system_login.py | 20 | ||||
-rwxr-xr-x | src/conf_mode/system_login.py | 21 | ||||
-rwxr-xr-x | src/op_mode/image_installer.py | 19 |
7 files changed, 5 insertions, 141 deletions
diff --git a/debian/control b/debian/control index 20b1a228c..c0f790228 100644 --- a/debian/control +++ b/debian/control @@ -127,8 +127,6 @@ Depends: # Live filesystem tools squashfs-tools, fuse-overlayfs, -# Tools for checking password strength - python3-cracklib, ## End installer auditd, iputils-arping, diff --git a/debian/vyos-1x.postinst b/debian/vyos-1x.postinst index ba97f37f6..fde58651a 100644 --- a/debian/vyos-1x.postinst +++ b/debian/vyos-1x.postinst @@ -195,10 +195,6 @@ if [ ! -x $PRECONFIG_SCRIPT ]; then EOF fi -# cracklib-runtime default database location -CRACKLIB_DIR=/var/cache/cracklib -CRACKLIB_DB=cracklib_dict - # create /opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script POSTCONFIG_SCRIPT=/opt/vyatta/etc/config/scripts/vyos-postconfig-bootup.script if [ ! -x $POSTCONFIG_SCRIPT ]; then @@ -210,15 +206,7 @@ if [ ! -x $POSTCONFIG_SCRIPT ]; then # This script is executed at boot time after VyOS configuration is fully applied. # Any modifications required to work around unfixed bugs # or use services not available through the VyOS CLI system can be placed here. -# -# T6353 - Just in case, check if cracklib was installed properly -# If the database file is missing, re-install the runtime package -# -if [ ! -f "${CRACKLIB_DIR}/${CRACKLIB_DB}.pwd" ]; then - mkdir -p $CRACKLIB_DIR - /usr/sbin/create-cracklib-dict -o $CRACKLIB_DIR/$CRACKLIB_DB \ - /usr/share/dict/cracklib-small -fi + EOF fi diff --git a/python/vyos/utils/auth.py b/python/vyos/utils/auth.py index a27d8a28a..a0b3e1cae 100644 --- a/python/vyos/utils/auth.py +++ b/python/vyos/utils/auth.py @@ -13,74 +13,10 @@ # You should have received a copy of the GNU Lesser General Public License along with this library; # if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -import cracklib -import math import re -import string -from enum import StrEnum -from decimal import Decimal from vyos.utils.process import cmd - -DEFAULT_PASSWORD = 'vyos' -LOW_ENTROPY_MSG = 'should be at least 8 characters long;' -WEAK_PASSWORD_MSG= 'The password complexity is too low - @MSG@' - - -class EPasswdStrength(StrEnum): - WEAK = 'Weak' - DECENT = 'Decent' - STRONG = 'Strong' - - -def calculate_entropy(charset: str, passwd: str) -> float: - """ - Calculate the entropy of a password based on the set of characters used - Uses E = log2(R**L) formula, where - - R is the range (length) of the character set - - L is the length of password - """ - return math.log(math.pow(len(charset), len(passwd)), 2) - -def evaluate_strength(passwd: str) -> dict[str, str]: - """ Evaluates password strength and returns a check result dict """ - charset = (cracklib.ASCII_UPPERCASE + cracklib.ASCII_LOWERCASE + - string.punctuation + string.digits) - - result = { - 'strength': '', - 'error': '', - } - - try: - cracklib.FascistCheck(passwd) - except ValueError as e: - # The password is vulnerable to dictionary attack no matter the entropy - if 'is' in str(e): - msg = str(e).replace('is', 'should not be') - else: - msg = f'should not be {e}' - result.update(strength=EPasswdStrength.WEAK) - result.update(error=WEAK_PASSWORD_MSG.replace('@MSG@', msg)) - else: - # Now check the password's entropy - # Cast to Decimal for more precise rounding - entropy = Decimal.from_float(calculate_entropy(charset, passwd)) - - match round(entropy): - case e if e in range(0, 59): - result.update(strength=EPasswdStrength.WEAK) - result.update( - error=WEAK_PASSWORD_MSG.replace('@MSG@', LOW_ENTROPY_MSG) - ) - case e if e in range(60, 119): - result.update(strength=EPasswdStrength.DECENT) - case e if e >= 120: - result.update(strength=EPasswdStrength.STRONG) - - return result - def make_password_hash(password): """ Makes a password hash for /etc/shadow using mkpasswd """ diff --git a/smoketest/scripts/cli/base_vyostest_shim.py b/smoketest/scripts/cli/base_vyostest_shim.py index f0674f187..edf940efd 100644 --- a/smoketest/scripts/cli/base_vyostest_shim.py +++ b/smoketest/scripts/cli/base_vyostest_shim.py @@ -94,18 +94,14 @@ class VyOSUnitTestSHIM: def cli_commit(self): if self.debug: print('commit') + self._session.commit() # During a commit there is a process opening commit_lock, and run() # returns 0 while run(f'sudo lsof -nP {commit_lock}') == 0: sleep(0.250) - # Return the output of commit - # Necessary for testing Warning cases - out = self._session.commit() # Wait for CStore completion for fast non-interactive commits sleep(self._commit_guard_time) - return out - def op_mode(self, path : list) -> None: """ Execute OP-mode command and return stdout diff --git a/smoketest/scripts/cli/test_system_login.py b/smoketest/scripts/cli/test_system_login.py index ed72f378e..d79f5521c 100755 --- a/smoketest/scripts/cli/test_system_login.py +++ b/smoketest/scripts/cli/test_system_login.py @@ -25,9 +25,7 @@ import shutil from base_vyostest_shim import VyOSUnitTestSHIM -from contextlib import redirect_stdout from gzip import GzipFile -from io import StringIO, TextIOWrapper from subprocess import Popen from subprocess import PIPE from pwd import getpwall @@ -44,7 +42,6 @@ from vyos.xml_ref import default_value base_path = ['system', 'login'] users = ['vyos1', 'vyos-roxx123', 'VyOS-123_super.Nice'] -weak_passwd_user = ['test_user', 'passWord1'] ssh_test_command = '/opt/vyatta/bin/vyatta-op-cmd-wrapper show version' @@ -197,20 +194,18 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): def test_system_login_user(self): for user in users: name = f'VyOS Roxx {user}' - passwd = f'{user}-pSWd-t3st' home_dir = f'/tmp/smoketest/{user}' - self.cli_set(base_path + ['user', user, 'authentication', 'plaintext-password', passwd]) + self.cli_set(base_path + ['user', user, 'authentication', 'plaintext-password', user]) self.cli_set(base_path + ['user', user, 'full-name', name]) self.cli_set(base_path + ['user', user, 'home-directory', home_dir]) self.cli_commit() for user in users: - passwd = f'{user}-pSWd-t3st' tmp = ['su','-', user] proc = Popen(tmp, stdin=PIPE, stdout=PIPE, stderr=PIPE) - tmp = f'{passwd}\nuname -a' + tmp = f'{user}\nuname -a' proc.stdin.write(tmp.encode()) proc.stdin.flush() (stdout, stderr) = proc.communicate() @@ -234,17 +229,6 @@ class TestSystemLogin(VyOSUnitTestSHIM.TestCase): tmp = cmd(f'sudo passwd -S {locked_user}') self.assertIn(f'{locked_user} P ', tmp) - def test_system_login_weak_password_warning(self): - self.cli_set(base_path + [ - 'user', weak_passwd_user[0], 'authentication', - 'plaintext-password', weak_passwd_user[1] - ]) - - out = self.cli_commit().strip() - - self.assertIn('WARNING: The password complexity is too low', out) - self.cli_delete(base_path + ['user', weak_passwd_user[0]]) - def test_system_login_otp(self): otp_user = 'otp-test_user' otp_password = 'SuperTestPassword' diff --git a/src/conf_mode/system_login.py b/src/conf_mode/system_login.py index 1e6061ecf..d3a969d9b 100755 --- a/src/conf_mode/system_login.py +++ b/src/conf_mode/system_login.py @@ -15,7 +15,6 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os -import warnings from passlib.hosts import linux_context from psutil import users @@ -25,17 +24,11 @@ from pwd import getpwuid from sys import exit from time import sleep -from vyos.base import Warning from vyos.config import Config from vyos.configverify import verify_vrf from vyos.template import render from vyos.template import is_ipv4 -from vyos.utils.auth import ( - DEFAULT_PASSWORD, - EPasswdStrength, - evaluate_strength, - get_current_user -) +from vyos.utils.auth import get_current_user from vyos.utils.configfs import delete_cli_node from vyos.utils.configfs import add_cli_node from vyos.utils.dict import dict_search @@ -153,18 +146,6 @@ def verify(login): if s_user.pw_name == user and s_user.pw_uid < MIN_USER_UID: raise ConfigError(f'User "{user}" can not be created, conflict with local system account!') - # T6353: Check password for complexity using cracklib. - # A user password should be sufficiently complex - plaintext_password = dict_search( - path='authentication.plaintext_password', - dict_object=user_config - ) or None - - if plaintext_password is not None: - result = evaluate_strength(plaintext_password) - if result['strength'] == EPasswdStrength.WEAK: - Warning(result['error']) - for pubkey, pubkey_options in (dict_search('authentication.public_keys', user_config) or {}).items(): if 'type' not in pubkey_options: raise ConfigError(f'Missing type for public-key "{pubkey}"!') diff --git a/src/op_mode/image_installer.py b/src/op_mode/image_installer.py index c6e9c7f6f..609b0b347 100755 --- a/src/op_mode/image_installer.py +++ b/src/op_mode/image_installer.py @@ -32,16 +32,10 @@ from errno import ENOSPC from psutil import disk_partitions -from vyos.base import Warning from vyos.configtree import ConfigTree from vyos.remote import download from vyos.system import disk, grub, image, compat, raid, SYSTEM_CFG_VER from vyos.template import render -from vyos.utils.auth import ( - DEFAULT_PASSWORD, - EPasswdStrength, - evaluate_strength -) from vyos.utils.io import ask_input, ask_yes_no, select_entry from vyos.utils.file import chmod_2775 from vyos.utils.process import cmd, run, rc_cmd @@ -89,9 +83,6 @@ MSG_WARN_ROOT_SIZE_TOOBIG: str = 'The size is too big. Try again.' MSG_WARN_ROOT_SIZE_TOOSMALL: str = 'The size is too small. Try again' MSG_WARN_IMAGE_NAME_WRONG: str = 'The suggested name is unsupported!\n'\ 'It must be between 1 and 64 characters long and contains only the next characters: .+-_ a-z A-Z 0-9' - -MSG_WARN_CHANGE_PASSWORD: str = 'Default password used. Consider changing ' \ - 'it on next login.' MSG_WARN_PASSWORD_CONFIRM: str = 'The entered values did not match. Try again' 'Installing a different image flavor may cause functionality degradation or break your system.\n' \ 'Do you want to continue with installation?' @@ -787,20 +778,10 @@ def install_image() -> None: while True: user_password: str = ask_input(MSG_INPUT_PASSWORD, no_echo=True, non_empty=True) - - if user_password == DEFAULT_PASSWORD: - Warning(MSG_WARN_CHANGE_PASSWORD) - else: - result = evaluate_strength(user_password) - if result['strength'] == EPasswdStrength.WEAK: - Warning(result['error']) - confirm: str = ask_input(MSG_INPUT_PASSWORD_CONFIRM, no_echo=True, non_empty=True) - if user_password == confirm: break - print(MSG_WARN_PASSWORD_CONFIRM) # ask for default console |