From 1e4b949a41305746c8ef0be4becc650af9e19270 Mon Sep 17 00:00:00 2001 From: Philip Guyton Date: Thu, 24 May 2018 19:57:41 +0100 Subject: [PATCH] remove --stdin option use for passwd #1927 By substituting 'usermod -p' for 'passwd --stdin' when setting user pass we avoid potential future issues on passwd's deprication / removal of the --stdin option: as has been observed in more defensive / progressive implementations of passwd. Elements of commit/pr: - Drop 'passwd --stdin' in favour of 'usermod -p'. - Use crypt module for password pre-encrypt as required for above change, ensuring sha-512 (observed current system default). - Use random full length (16 chars) salt in above. - Add comments for post python3 move enhancements re crypt's use. --- src/rockstor/system/users.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/rockstor/system/users.py b/src/rockstor/system/users.py index d240c2d23..db159bd66 100644 --- a/src/rockstor/system/users.py +++ b/src/rockstor/system/users.py @@ -28,6 +28,9 @@ from shutil import move from tempfile import mkstemp import chardet +import random +import string +import crypt import logging logger = logging.getLogger(__name__) @@ -36,7 +39,6 @@ GROUPADD = '/usr/sbin/groupadd' USERDEL = '/usr/sbin/userdel' GROUPDEL = '/usr/sbin/groupdel' -PASSWD = '/usr/bin/passwd' USERMOD = '/usr/sbin/usermod' SMBPASSWD = '/usr/bin/smbpasswd' CHOWN = '/usr/bin/chown' @@ -128,14 +130,22 @@ def get_epasswd(username): def usermod(username, passwd): - cmd = [PASSWD, '--stdin', username] + # TODO: 'salt = crypt.mksalt()' # Python 3.3 onwards provides system best. + # Salt starting "$6$" & of 19 chars signifies SHA-512 current system best. + # Salt must contain only [./a-zA-Z0-9] chars (bar first 3 if len > 2) + salt_header = '$6$' # SHA-512 + rnd = random.SystemRandom() + salt = ''.join([rnd.choice(string.ascii_letters + string.digits + './') + for _ in range(16)]) + crypted_passwd = crypt.crypt(passwd.encode('utf8'), salt_header + salt) + cmd = [USERMOD, '-p', crypted_passwd, username] p = subprocess.Popen(cmd, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) - out, err = p.communicate(input=passwd.encode('utf8')) + out, err = p.communicate(input=None) rc = p.returncode - if (rc != 0): + if rc != 0: raise CommandException(cmd, out, err, rc) - return (out, err, rc) + return out, err, rc def smbpasswd(username, passwd):