From: Thomas Walker Lynch Date: Wed, 31 Aug 2022 16:28:04 +0000 (+0000) Subject: fix_mode with useful comments X-Git-Url: https://git.reasoningtechnology.com/style/static/gitweb.js?a=commitdiff_plain;h=f6827d8f03431f8aee93d5dae5ae79104e04e056;p=subu fix_mode with useful comments --- diff --git a/user/cantari/fix_mode b/user/cantari/fix_mode new file mode 100755 index 0000000..9faf4b8 --- /dev/null +++ b/user/cantari/fix_mode @@ -0,0 +1,90 @@ +#!/bin/python +# +# The subu admin is member of all subu users groups, so group rw enables +# administration of file. +# +# Consequently, in the subu environement we may think of the group permissions +# as 'admin permissions'. We remove x from administrator permissions because the +# administor does not want to execute user's executables. +# +# This script exists because it is possible for users to mess with the subu +# admin permissions, because they are the same as the user's group +# permissions. I should instead be using acls instead. +# +# Here is a flaw in this approach: when the administrator moves files from, say, +# Thomas/repo to Thomas/archive, the set gid bit on the archive directory causes +# the file to to have group ownership of thomas-archive, while the user remains +# thomas-repo. Now, as the thomas-archive does not own the file thomas-archive +# may not change the permissions on the file. Compounding this problem, since +# we cleared the group x bit (except for directories), thomas-archive may not +# execute the file even if he wants to. Compunding this yet further, the original +# file owner, who still owns the file, can not change the permissions because +# the original file owner has no permissions on the directory. +# +# ^^ hence the prior owner remains on the transferred file, that is kind of +# nice, so we know where the file came from - but this is not a good way to keep +# track of the history of ownership. BSD has a mode where the set UID bit on a +# directory has an analogous function to the set GID bit, but Linux does not. We +# do not know if a whole file tree was transferred, we can end up with a +# mess. The solution seems to be that the admin needs to manually 'chown -R +# target_user:target_group' the transferred files and assign them to the target +# user. +# +# Another interesting permissions use case is that of the subu repo and subu Lustucru. +# Lustuctru is a member of group repo. subu repo does not have sudo access. However +# the Lustucur project uses the chroot command, so it needs it. I did not want to give +# sudo to all repos projects, so I created subu Lustucru that does have sudo. Lustucru +# makes use of the repo/Lustucru files by being in the repo group. Now the repo group +# has two purposes, one being admin, and one to give group members access to files. This +# is not going to work because the admin set the mode bits to turn off x. I.e. there +# are conflicts between what the admin wants as a group member and what subu Lustucru wants +# as a group member. +# +# modes changes occur on the symbolic links directly, i.e. this script +# does not follow sym links. +# +# We start by clearing all mode bits that we might want cleared. Then +# we set mode bits we know we want. + +import sys +import os +import stat + +def mode_clear(mode): + return mode & ~(stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH | stat.S_IXGRP) + +# files +# user is as found +# administrator is given rw permissions +# +def mode_file(mode): + mode = mode_clear(mode) + return mode | stat.S_IRGRP | stat.S_IWGRP + +# directories +# administrator is given rwx, and set gid so that files made in the directory +# will be made in the user's group, which the administrator is a member. +# +def mode_dir(mode): + mode = mode_clear(mode) + return mode | stat.S_IRGRP | stat.S_IWGRP | stat.S_IXGRP | stat.S_ISGID + +# By default os.walk does not follow symlinks, so dn will be a directory not a +# link to one. stat follows symlinks, lstat does not, so we use lstat +# +exclude = set(['.cache' ,'.dbus' ,'.ssh' ,'.gnupg']) +for darg in sys.argv[1:]: + if os.path.isdir(darg): + for dn, dnp1s, files in os.walk(darg): + dnp1s[:] = [d for d in dnp1s if d not in exclude] + dn_mode = os.lstat(dn).st_mode + if not stat.S_ISDIR(dn_mode): + print("os.walk returned a non directory for dn, strange, ignoring it.") + else: + os.chmod(dn ,mode_dir(dn_mode)) + for f in files: + f_path = "/".join([dn ,f]) + f_mode = os.lstat(f_path).st_mode + os.chmod(f_path ,mode_file(f_mode) ,follow_symlinks=False) + + diff --git a/user/cantari/subu_add b/user/cantari/subu_add index 4363865..4179307 100755 --- a/user/cantari/subu_add +++ b/user/cantari/subu_add @@ -4,7 +4,8 @@ # # wish we could set the uids and gids so that backups would restore properly on other systems but it is too much trouble # to do in a shell script. Perhaps in the python code for the actual release. -set -x + +#set -x subu=$1 stem=$2 diff --git a/user/cantari/subu_del b/user/cantari/subu_del index a8a7efd..e139fba 100755 --- a/user/cantari/subu_del +++ b/user/cantari/subu_del @@ -2,17 +2,26 @@ # must have command user-stem # user-stem is in the system repo # -# currently this is setup to be run by any user who has sudo - it doesn't have to be run by the user-admin account; though chances are it will be. +# currently this is setup to be run by any user who has sudo - it doesn't have +# to be run by the user-admin account; though chances are it will be. # -# userdel -r deletes both the /var/spool/mail/user and the user's home directory. We don't want to delete the old data just in case there -# is something important there. However we can not leve the old /var/spool/mail/user file under /var/spool/mail in case another subu is -# created later with the same name. Hence we will move the /var/spool/mail/user file into the users home directory. We will give ownership -# of the old home directory to the admin. +# userdel -r deletes both the /var/spool/mail/user and the user's home +# directory. We don't want to delete the old data just in case there is +# something important there. However we can not leave the old +# /var/spool/mail/user file under /var/spool/mail in case another subu is +# created later with the same name. Hence we will move the /var/spool/mail/user +# file into the users home directory. We will give ownership of the old home +# directory to the admin. # -# I have run into a problem that subu users do not inherit the MAIL variable, I wouldn't trust it anyway. I do not know if userdel -r -# references the MAIL variable. I will hard code a local variable to /var/sppol/mail. This must be changed for systems that put the mail spool -# file eleswhere. +# I have run into a problem that subu users do not inherit the MAIL variable, I +# wouldn't trust it anyway. I do not know if userdel -r references the MAIL +# variable. I will hard code a local variable to /var/spool/mail. This must be +# changed for systems that put the mail spool file eleswhere. # +# It seems that upon upgrade to Fedora 36 it stopped making a /var/spool/mail +# file for a new user. Anyway I am getting errors on that.file not existing, so +# added a conditional for if /var/spool/mail/user file + #set -x subu=$1 @@ -35,13 +44,18 @@ fi subu_username="$stem-$subu" admin_username="$stem-admin" -subu_home="/home/$stem/$subu"_root +subu_home="/home/$stem/$subu" archive_suffix=";1" archive_home="$subu_home$archive_suffix" mail_source_dir="/var/spool/mail" mail_source_file="$mail_source_dir/$subu_username" mail_target_file="$subu_home/mail_spool" +if ! id "$subu_username" &>/dev/null; then + echo "no such user" + exit 1 +fi + if [ -e "$archive_home" ]; then echo "there is already a saved directory for a deleted subu with this name, move this out of the way first: $archive_home" exit 1 @@ -56,12 +70,23 @@ if [ -e "$mail_target_file" ]; then exit 1 fi -sudo killall --signal 5 --wait --user "$subu_username" -sudo mv "$mail_source_file" "$mail_target_file" +sudo killall --signal 5 --wait --user "$subu_username" && true + +if [ -e "$mail_source_file" ]; then + sudo mv "$mail_source_file" "$mail_target_file" +fi sudo chmod -R go-rwx "$subu_home" sudo chown -R "$admin_username":"$admin_username" "$subu_home" mv "$subu_home" "$archive_home" sudo groupdel -f "$subu_username" sudo userdel "$subu_username" +# common to follow up with rm -r and get an error that gvfs can not be deleted +# (probably better to move it trash or tmp than rm -r, and let the system clean it up later) +# rather surprising as we did a kill all on its processes +gvfs="$archive_home/.cache/gvfs" +if [ -e "$gvfs" ]; then + sudo umount "$gvfs" +fi + #set +x