I would like to programmatically repair the ownership on Linux systems for files within each users home directory which reside under /home
. From https://serverfault.com/a/146709/75044 the script below seems ideal except, some of the users are not in the /etc/passwd
as they are externally authenticated.
The users which are externally authenticated, do have a uid and gid associated with their home directories though. The externally authenticated users uid
and gid
produced from the id
command do not match the ls -ln
respective group and user id. I did not catch this originally due to sanitizing the output. A mapping is being performed so the only way to correctly perform this in my opinion is to leverage the uid
and gid
from the directory listing.
Instead of depending on the /etc/passwd
, how can we obtain and use the uid
and gid
from each users home directory to then recursively apply the same uid and gid ownership to the objects within their respective home directories?
#!/bin/bash
while IFS=':' read -r login pass uid gid uname homedir comment; do
if [[ "$homedir" = **/home/** ]]; then
if [ -d "$homedir" ]; then
echo chown -R $uid:$gid "$homedir";
fi
fi
done < /etc/passwd
An example user that's external authenticated would have a home directory that lives user /home
drwx------+ 3 DOMAIN\user DOMAIN\DOMAIN USERS 4096 Jan 1 1969 user
but in it's uid/gid format would look like:
drwx------+ 3 12345 01234 4096 Jan 1 1969 user
Output from id
(the uid/gid does not match the directory listing):
$ id DOMAIN\\user
uid=2000234(DOMAIN) gid=2000349(DOMAIN\domain users) groups=2056789(DOMAIN\domain users) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
$ stat -c "%n %u:%g" /home/user/
/home/user/ 12345:01234
I assume it would be easier to obtain and apply using the uid and gid verse parsing the user and group names.
An example of a local user is as follows:
drwx------. 4 1000 1000 4096 Jul 21 02:04 user2
drwx------. 4 user2 user2 4096 Jul 21 02:04 user2
$ id user2
uid=1000(user2) gid=1000(user2) groups=1000(user2),4(adm),190(systemd-journal)
edit
Another option would be to list the file in /home
, feed through stat
and apply the permissions to those files that do not match. An example to just change the group would be
find /home -maxdepth 1
but we do not want to include /home in the listing
stat -c %g
against home directory and set to variable $GID
find \! -gid $GID -exec chown :$GID {} \;
if $GID for a child file or folder of the home directory does not match, fix it
Something like the following which does not work would suffice
find . -exec sh -c '
for f do
GID=$(stat -c %g)
chown :$GID $f
' find-sh {} \;
Assuming that the owner and group of all home directories match the corresponding user, you can set the ownership for all contained subdirectories and files to the same values.
Note that there might be files or directories that deliberately have a different owner or group. Blindly changing the owner or group might break access for other users or applications.
This (untested) command will show the commands to recursively change the owner and group IDs to the values taken from the home directory:
for i in /home/*/
do
echo chown -Rh $(stat -c "%u:%g" "$i") "$i"
done
You can also use chown --reference=RFILE
to copy the ownership data from a reference, but this will not show the actual uid and gid values.
for i in /home/*/
do
echo chown -Rh --reference="$i" "$i"
done
When you have manually checked that everything is correct, remove the echo
to actually run the commands.