8

i.e:

Suppose the directory permission is 700, and the file under the directory is 570

Then the effective permission of the file is 500

Is there such a command that lists the effective permission by recursively checking parent permissions?

4 Answers 4

6

There is no such command and no simple way to do it, especially as both the file and the directories might have ACLs set in addition to the traditional permissions making the effective file permissions more complex to compute and display. Moreover, your question assumes there is a single path to the file but symbolic links potentially presents in the path should be first resolved as their permissions do not matter, the file might also have multiple hard-links so might be reachable from another directory. The user might also be able to access it through a different path if either loopback/bind mounts are in place or the user is running in a chrooted environment.

In any case, what you can do is to impersonate a user and check if the file while accessed through a given path is readable, writable and/or executable by him/her.

Something like:

#!/bin/ksh
[[ $# != 2 ]] && { echo Usage $0 user file; exit ; }
dir=$(\cd $(dirname "$2");/bin/pwd)
file=$(basename "$2")
su $1 ksh -c '
cd $2 2>/dev/null || { echo "---" ; exit ; }
[[ -r "$3" ]] && p=r || p=-
[[ -w "$3" ]] && p=${p}w || p=${p}-
[[ -x "$3" ]] && p=${p}x || p=${p}-
printf "%s %s/%s\n" $p "$2" "$3"
' "$1" "$dir" "$file"

This will show the effective rights for the user on that particular file using the traditional rwx syntax. Note that this script might give false negative results if the user launching has not root privileges (or equivalent) and has no read access on the target directory.

4
  • 1
    You make several excellent points: Different hard links to the same inode can have different “effective permissions” if they are in different directories. Users can access directories through chroot or mount points that they wouldn’t be able to access directly. (Of course this applies to remote network mounts as well as loopback mounts.) One caveat: the user should use your script with an absolute path. If I cd deep into my directory structure and then run your script on a relative filename, that will defeat the point. Dec 14, 2012 at 20:52
  • @Scott, thanks for the comment, script updated to fix that issue.
    – jlliagre
    Dec 15, 2012 at 7:21
  • I’m not sure that works. Consider (1) I type cd ~/private/dir1, where private is 700 and dir1 is 755, and type foo fred myfile, where foo is your script and myfile is 644. Your script will su to fred, (successfully) cd to ., and report r–– — even though fred has no access to ~/scott/private. (2) I cd ~/dir2/dir3, where dir2 and dir3 are 755, and type foo fred ../myfile2, where myfile2 is a file in dir2. Your script will cd to .. (dir2) and then try to access ../myfile2 — which doesn’t exist, relative to dir2. Dec 17, 2012 at 22:48
  • @Scott, you are right again. Fixed.
    – jlliagre
    Dec 17, 2012 at 23:10
2

This is not so very easy to solve. Especially, the "effective" file permissions (a concept which is in this context unknown to me) is not so easy to determine.

You can access a file if all the directories leading to it are "executable". If you know the file's names, you do not need read access.

(E. g., sometimes, I make home directories 710 in order to give x access to other members of the same group. So no one else sees what I have in my ~, but they can use it if I tell them what is there.)

If the question is about accessing an existing file, the answer is different from creating or removing a file. In the latter case, the parent directory of the file(-to-be) bust be writable.

OTOH, if I do not have the x of a directory in the file's path, I cannot even determine if the file exists, and thus also not which permissions the file has. You can argue that then the effective permission would be 0, but I don't find it sensible to tell something about file permissions when I don't even know if the file exists.

But if you want so, you take the mask of each directory, do & 0111, & the masks together, and if there is a 0 where a 1 should be, you put a 0 into the file's "effective permission".

For creating and removing, you determine the parent directory's effective permission and look if it is writable and executable.

So in a 700 directory, a 570 becomes 500.

4
  • What’s your point? To quote you, “This scenario says that I – as owner – … cannot modify the file.” In other words, the owner has read+execute permission. Everybody else has no access — hence, the effective permission is 500. The fact that a different set of parameters (directory = 500, file = 600) has a different result doesn’t invalidate the example that the OP gave. Dec 14, 2012 at 0:51
  • @Scott My point is that this is a bad example, because it might suggest that you just have to AND together the mask and get the result. This is not the case. But maybe I just got this wrong from my understanding...
    – glglgl
    Dec 14, 2012 at 7:11
  • @Scott I made more thoughts about it and rephrased the complete answer.
    – glglgl
    Dec 14, 2012 at 7:21
  • Well, systems that have ACLs (including *nix and Windows) have a concept of “effective permission(s)”, but they generally deal only with the interaction of ACEs within one ACL, and not with the directories leading up (down?) to the target. Dec 14, 2012 at 20:51
2

The other answers are correct. However you can use a bash one-liner to list the permissions of the directory hierarchy. First change to the directory in question, and then run:

pushd .; while [ `pwd` != / ]; do ls -ld `pwd`; cd ..; done; popd
2
  • Thank you for posting this. Very useful for a quick overview.
    – semtex41
    Feb 24, 2017 at 16:25
  • A version with more information and slightly fancier formatting: pushd . >/dev/null; while [ `pwd` != / ]; do printf '%-50s' `pwd`; stat `pwd` | grep 'Access: (' | sed "s/Access//g" ; cd ..; done; popd>/dev/null
    – pgr
    Nov 4, 2021 at 14:41
1

You can use namei with option -m or -l, and then do the calculation yourself.

$ namei -l /home/theuser/.ssh/authorized_keys
f: /home/theuser/.ssh/authorized_keys
dr-xr-xr-x root     root  /
drwxr-xr-x root     root  home
drwx------ theuser users theuser
drwxr-xr-x theuser users .ssh
-rw------- theuser users authorized_keys

You must log in to answer this question.