You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qubes-installer-qubes-os/anaconda/tests/pyanaconda_tests/user_create_test.py

356 lines
15 KiB

# vim:set fileencoding=utf-8
#
# Copyright (C) 2015 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use,
# modify, copy, or redistribute it subject to the terms and conditions of
# the GNU General Public License v.2, or (at your option) any later version.
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details. You should have received a copy of the
# GNU General Public License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA. Any Red Hat trademarks that are incorporated in the
# source code or documentation are not subject to the GNU General Public
# License and may only be used or replicated with the express permission of
# Red Hat, Inc.
#
from pyanaconda import users
import unittest
import tempfile
import shutil
import os
import crypt
import platform
import glob
@unittest.skipIf(os.geteuid() != 0, "user creation must be run as root")
class UserCreateTest(unittest.TestCase):
def setUp(self):
self.users = users.Users()
# Create a temporary directory with empty passwd and group files
self.tmpdir = tempfile.mkdtemp()
os.mkdir(self.tmpdir + "/etc")
open(self.tmpdir + "/etc/passwd", "w").close()
open(self.tmpdir + "/etc/group", "w").close()
open(self.tmpdir + "/etc/shadow", "w").close()
open(self.tmpdir + "/etc/gshadow", "w").close()
# Copy over enough of libnss for UID and GID lookups to work
with open(self.tmpdir + "/etc/nsswitch.conf", "w") as f:
f.write("passwd: files\n")
f.write("shadow: files\n")
f.write("group: files\n")
f.write("initgroups: files\n")
if platform.architecture()[0].startswith("64"):
libdir = "/lib64"
else:
libdir = "/lib"
os.mkdir(self.tmpdir + libdir)
for lib in glob.glob(libdir + "/libnss_files*"):
shutil.copy(lib, self.tmpdir + lib)
def tearDown(self):
shutil.rmtree(self.tmpdir)
def _readFields(self, filename, key):
"""Look for a line in a password or group file where the first field
matches key, and return the record as a list of fields.
"""
with open(self.tmpdir + filename) as f:
for line in f:
fields = line.strip().split(':')
if fields[0] == key:
return fields
return None
def create_group_test(self):
"""Create a group."""
self.users.createGroup("test_group", root=self.tmpdir)
fields = self._readFields("/etc/group", "test_group")
self.assertIsNotNone(fields)
self.assertEqual(fields[0], "test_group")
fields = self._readFields("/etc/gshadow", "test_group")
self.assertIsNotNone(fields)
self.assertEqual(fields[0], "test_group")
def create_group_gid_test(self):
"""Create a group with a specific GID."""
self.users.createGroup("test_group", gid=47, root=self.tmpdir)
fields = self._readFields("/etc/group", "test_group")
self.assertIsNotNone(fields)
self.assertEqual(fields[0], "test_group")
self.assertEqual(fields[2], "47")
def create_group_exists_test(self):
"""Create a group that already exists."""
with open(self.tmpdir + "/etc/group", "w") as f:
f.write("test_group:x:47:\n")
self.assertRaises(ValueError, self.users.createGroup, "test_group", root=self.tmpdir)
def create_group_gid_exists_test(self):
"""Create a group with a GID that already exists."""
with open(self.tmpdir + "/etc/group", "w") as f:
f.write("gid_used:x:47:\n")
self.assertRaises(ValueError, self.users.createGroup, "test_group", gid=47, root=self.tmpdir)
def create_user_test(self):
"""Create a user."""
self.users.createUser("test_user", root=self.tmpdir)
pwd_fields = self._readFields("/etc/passwd", "test_user")
self.assertIsNotNone(pwd_fields)
self.assertEqual(pwd_fields[0], "test_user")
# Check that the fields got the right default values
# UID + GID set to some sort of int
self.assertTrue(isinstance(int(pwd_fields[2]), int))
self.assertTrue(isinstance(int(pwd_fields[3]), int))
# home is /home/username
self.assertEqual(pwd_fields[5], "/home/test_user")
# shell set to something
self.assertTrue(pwd_fields[6])
shadow_fields = self._readFields("/etc/shadow", "test_user")
self.assertIsNotNone(shadow_fields)
self.assertEqual(shadow_fields[0], "test_user")
# Ensure the password is locked
self.assertTrue(shadow_fields[1].startswith("!"))
# Ensure the date of last password change is empty
self.assertEqual(shadow_fields[2], "")
# Check that the user group was created
grp_fields = self._readFields("/etc/group", "test_user")
self.assertIsNotNone(grp_fields)
self.assertEqual(grp_fields[0], "test_user")
# Check that user group's GID matches the user's GID
self.assertEqual(grp_fields[2], pwd_fields[3])
gshadow_fields = self._readFields("/etc/gshadow", "test_user")
self.assertIsNotNone(gshadow_fields)
self.assertEqual(gshadow_fields[0], "test_user")
def create_user_text_options_test(self):
"""Create a user with the text fields set."""
self.users.createUser("test_user", gecos="Test User", homedir="/home/users/testuser", shell="/bin/test", root=self.tmpdir)
pwd_fields = self._readFields("/etc/passwd", "test_user")
self.assertIsNotNone(pwd_fields)
self.assertEqual(pwd_fields[0], "test_user")
self.assertEqual(pwd_fields[4], "Test User")
self.assertEqual(pwd_fields[5], "/home/users/testuser")
self.assertEqual(pwd_fields[6], "/bin/test")
# Check that the home directory was created
self.assertTrue(os.path.isdir(self.tmpdir + "/home/users/testuser"))
def create_user_groups_test(self):
"""Create a user with a list of groups."""
# Create one of the groups
self.users.createGroup("test3", root=self.tmpdir)
# Create a user and add it three groups, two of which do not exist,
# and one which specifies a GID.
self.users.createUser("test_user", groups=["test1", "test2(5001)", "test3"], root=self.tmpdir)
grp_fields1 = self._readFields("/etc/group", "test1")
self.assertEqual(grp_fields1[3], "test_user")
grp_fields2 = self._readFields("/etc/group", "test2")
self.assertEqual(grp_fields2[3], "test_user")
self.assertEqual(grp_fields2[2], "5001")
grp_fields3 = self._readFields("/etc/group", "test3")
self.assertEqual(grp_fields3[3], "test_user")
def create_user_groups_gid_conflict_test(self):
"""Create a user with a bad list of groups."""
# Create one of the groups
self.users.createGroup("test3", gid=5000, root=self.tmpdir)
# Add test3 to the group list with a different GID.
self.assertRaises(ValueError, self.users.createUser,
"test_user", groups=["test3(5002)"], root=self.tmpdir)
def create_user_password_test(self):
"""Create a user with a password."""
self.users.createUser("test_user1", password="password", root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "test_user1")
self.assertIsNotNone(shadow_fields)
# Make sure the password works
self.assertEqual(crypt.crypt("password", shadow_fields[1]), shadow_fields[1])
# Set the encrypted password for another user with isCrypted
cryptpw = shadow_fields[1]
self.users.createUser("test_user2", password=cryptpw, isCrypted=True, root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "test_user2")
self.assertIsNotNone(shadow_fields)
self.assertEqual(cryptpw, shadow_fields[1])
# Set an empty password
self.users.createUser("test_user3", password="", root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "test_user3")
self.assertIsNotNone(shadow_fields)
self.assertEqual("", shadow_fields[1])
def create_user_lock_test(self):
"""Create a locked user account."""
# Create an empty, locked password
self.users.createUser("test_user1", lock=True, password="", root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "test_user1")
self.assertIsNotNone(shadow_fields)
self.assertEqual("!", shadow_fields[1])
# Create a locked password and ensure it can be unlocked (by removing the ! at the front)
self.users.createUser("test_user2", lock=True, password="password", root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "test_user2")
self.assertIsNotNone(shadow_fields)
self.assertTrue(shadow_fields[1].startswith("!"))
self.assertEqual(crypt.crypt("password", shadow_fields[1][1:]), shadow_fields[1][1:])
def create_user_uid_test(self):
"""Create a user with a specific UID."""
self.users.createUser("test_user", uid=1047, root=self.tmpdir)
pwd_fields = self._readFields("/etc/passwd", "test_user")
self.assertIsNotNone(pwd_fields)
self.assertEqual(pwd_fields[2], "1047")
def create_user_gid_test(self):
"""Create a user with a specific GID."""
self.users.createUser("test_user", gid=1047, root=self.tmpdir)
pwd_fields = self._readFields("/etc/passwd", "test_user")
self.assertIsNotNone(pwd_fields)
self.assertEqual(pwd_fields[3], "1047")
grp_fields = self._readFields("/etc/group", "test_user")
self.assertIsNotNone(grp_fields)
self.assertEqual(grp_fields[2], "1047")
def create_user_algo_test(self):
"""Create a user with a specific password algorithm."""
self.users.createUser("test_user1", password="password", algo="md5", root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "test_user1")
self.assertIsNotNone(shadow_fields)
self.assertTrue(shadow_fields[1].startswith("$1$"))
self.users.createUser("test_user2", password="password", algo="sha512", root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "test_user2")
self.assertIsNotNone(shadow_fields)
self.assertTrue(shadow_fields[1].startswith("$6$"))
def create_user_exists_test(self):
"""Create a user that already exists."""
with open(self.tmpdir + "/etc/passwd", "w") as f:
f.write("test_user:x:1000:1000::/:/bin/sh\n")
self.assertRaises(ValueError, self.users.createUser, "test_user", root=self.tmpdir)
def create_user_uid_exists_test(self):
"""Create a user with a UID that already exists."""
with open(self.tmpdir + "/etc/passwd", "w") as f:
f.write("conflict:x:1000:1000::/:/bin/sh\n")
self.assertRaises(ValueError, self.users.createUser, "test_user", uid=1000, root=self.tmpdir)
def create_user_gid_exists_test(self):
"""Create a user with a GID of an existing group."""
self.users.createGroup("test_group", gid=5000, root=self.tmpdir)
self.users.createUser("test_user", gid=5000, root=self.tmpdir)
passwd_fields = self._readFields("/etc/passwd", "test_user")
self.assertIsNotNone(passwd_fields)
self.assertEqual(passwd_fields[3], "5000")
def set_user_ssh_key_test(self):
keydata = "THIS IS TOTALLY A SSH KEY"
self.users.createUser("test_user", homedir="/home/test_user", root=self.tmpdir)
self.users.setUserSshKey("test_user", keydata, root=self.tmpdir)
keyfile = self.tmpdir + "/home/test_user/.ssh/authorized_keys"
self.assertTrue(os.path.isfile(keyfile))
with open(keyfile) as f:
output_keydata = f.read()
self.assertEqual(keydata, output_keydata.strip())
def set_root_password_test(self):
password = "password1"
# Initialize a root user with an empty password, like the setup package would have
with open(self.tmpdir + "/etc/passwd", "w") as f:
f.write("root:x:0:0:root:/root:/bin/bash\n")
with open(self.tmpdir + "/etc/shadow", "w") as f:
f.write("root:*:16489:0:99999:7:::\n")
self.users.setRootPassword(password, root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "root")
self.assertEqual(crypt.crypt(password, shadow_fields[1]), shadow_fields[1])
# Try a different password with isLocked=True
password = "password2"
self.users.setRootPassword(password, isLocked=True, root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "root")
self.assertTrue(shadow_fields[1].startswith("!"))
self.assertEqual(crypt.crypt(password, shadow_fields[1][1:]), shadow_fields[1][1:])
# Try an encrypted password
password = "$1$asdf$password"
self.users.setRootPassword(password, isCrypted=True, root=self.tmpdir)
shadow_fields = self._readFields("/etc/shadow", "root")
self.assertEqual(password, shadow_fields[1])
def create_user_reuse_home_test(self):
# Create a user, reusing an old home directory
os.makedirs(self.tmpdir + "/home/test_user")
os.chown(self.tmpdir + "/home/test_user", 500, 500)
self.users.createUser("test_user", homedir="/home/test_user", uid=1000, gid=1000, root=self.tmpdir)
passwd_fields = self._readFields("/etc/passwd", "test_user")
self.assertIsNotNone(passwd_fields)
self.assertEqual(passwd_fields[2], "1000")
self.assertEqual(passwd_fields[3], "1000")
stat_fields = os.stat(self.tmpdir + "/home/test_user")
self.assertEqual(stat_fields.st_uid, 1000)
self.assertEqual(stat_fields.st_gid, 1000)
def create_user_gid_in_group_list_test(self):
"""Create a user with a GID equal to that of one of the requested groups"""
self.users.createUser("test_user", gid=1047, groups=["test_group(1047)"], root=self.tmpdir)
# Ensure that the user's GID is equal to the GID requested
pwd_fields = self._readFields("/etc/passwd", "test_user")
self.assertIsNotNone(pwd_fields)
self.assertEqual(pwd_fields[3], "1047")
# and that the requested group has the right GID
grp_fields = self._readFields("/etc/group", "test_group")
self.assertIsNotNone(grp_fields)
self.assertEqual(grp_fields[2], "1047")