109

*nix user permissions are really simple, but things can get messy when you have to take in account all the parent directory access before reaching a given file. How can I check if the user has enough privileges? If not, then which directory is denying access?

For example, suppose a user joe, and the file /long/path/to/file.txt. Even if file.txt was chmoded to 777, joe still has to be able to access /long/, and then /long/path/ and then /long/path/to/ before. What I need is a way to automatically check this. If joe does not have access, I would also like to know where he has been denied. Maybe he can access /long/, but not /long/path/.

1
  • So you're question is more "how to determine why a user cannot access a file"? :) Commented Nov 14, 2019 at 23:34

6 Answers 6

111

To verify access visually, you can use

namei -m /path/to/really/long/directory/with/file/in

which will output all of the permissions in the path in a vertical list.

or

namei -l /path/to/really/long/directory/with/file/in

to list all owners and the permissions. Other answers explain how to verify this programmatically.

3
  • 2
    This should be the right answer. In fact using namei <path> || exit 1 allows you to detect a permission problem much easily in a script. Commented Jun 2, 2016 at 10:01
  • 30
    it doesn't answer directly whether joe has access to the file. Commented Nov 6, 2017 at 20:03
  • 1
    This also does not elucidate how access control lists might influence things. Commented Sep 15, 2021 at 0:41
30

If you have root access, impersonate the user, then run test -r (read), test -w (write), or test -x (execute) to check whether the user can read/write/execute the given file.

sudo -u otheruser test -w /file/to/test || {
   echo "otheruser cannot write the file"
}
2
  • 3
    This is exact answer what I was searching for. Title of this question could be misleading. Commented Apr 29, 2020 at 5:01
  • 3
    a slight embellishment to check if a process running as "USER:GROUP" can access a given file would be the following command: sudo su - USER -g GROUP -s /bin/bash -c "test -r /path/to/file" Commented Jan 23, 2021 at 14:53
21

You can use bash to do this.

$ cat check-permissions.sh
#!/bin/bash
file=$1
# Handle non-absolute paths
if ! [[ "$file" == /* ]] ; then
    path=.
fi
dirname "$file" | tr '/' $'\n' | while read part ; do
    path="$path/$part"
    # Check for execute permissions
    if ! [[ -x "$path" ]] ; then
        echo "'$path' is blocking access."
    fi
done
if ! [[ -r "$file" ]] ; then
    echo "'$file' is not readable."
fi
$ ./check-permissions.sh /long/path/to/file.txt

To check this for a specific user, you can use sudo.

sudo -u joe ./check-permissions.sh /long/path/to/file.txt
11
  • sudo -u joe script . Here script is the name of the script file right? so your telling sudo to act like joe was calling the script? Commented Jul 9, 2013 at 14:24
  • Precisely. I have modified my answer to clarify that. Commented Jul 9, 2013 at 14:31
  • I made a slight modification to my script to handle non-absolute paths. Commented Jul 9, 2013 at 14:47
  • @EvanTeitelman With an absolute path, did you mean to initialize path to be empty? or /? Commented Jul 9, 2013 at 20:31
  • @Gilles: I meant for it to be empty. In the example, path is set to /long the first time around the loop, which is correct. Should I set path to nothing explicitly (path=)? Also, thanks for simplifying out my use of tr. Commented Jul 9, 2013 at 20:58
5

As I got from your question, you should check it for different users (not only joe), so in that case the easiest way is to recursivly check it via sudo like this:

FILE=$1 ; T_USER=$2 ;
if sudo -u $T_USER [ -r "$FILE" ] ; then
    echo "original file $1 is readable for $T_USER"
else
    while sudo -u $T_USER [ ! -x "$FILE" ] ; do FILE=$(dirname "$FILE") ; done
    echo "only $FILE is readable for $T_USER"
fi

usage:

./script.sh /long/path/to/file.txt joe
6
  • Joe needs execute permissions on the directories, not read permissions. Commented Jul 9, 2013 at 14:20
  • @EvanTeitelman yes, you're right. Fixed. Commented Jul 9, 2013 at 14:29
  • @rush I tried to test it using the following file: /root/test/test.txt (permissions are 0755, 0700, and 0777). I issued ./script.sh /root/test/test.txt joe and it echoed original file /root/test/test.txt is readable for joe. Also, while trying this I misstyped the test dir: ./script.sh /root/tst/test.txt joe, and it echoed original file /root/tst/test.txt is readable for joe. Did I missed something? Commented Jul 10, 2013 at 17:46
  • @Metalcoder sorry, it's my fault. There was one extra exclamation. It's removed now, you can try it one more time, it should work fine now. Commented Jul 10, 2013 at 17:50
  • @rush it worked! That extra exclamation negates the result of -r $FILE, right? Commented Jul 10, 2013 at 18:10
2

Here's my attempt at providing this functionality. I've opted to use stat, a while loop, and dirname.

I've created this script, walkdir.bash:

#/bin/bash

cwd="$1"
while [ "x$cwd" != x/ ]; do
  info=`stat "$cwd" |grep "Access: ("`
  printf "%s : %s\n" "$info" "$cwd"

  cwd=`dirname "$cwd"`;
done

You run it like so:

$ walkdir.bash "/home/saml/blog/vmware_networking_tutorial/url.txt"
Access: (0664/-rw-rw-r--)  Uid: (  500/    saml)   Gid: (  501/    saml) : /home/saml/blog/vmware_networking_tutorial/url.txt
Access: (0775/drwxrwxr-x)  Uid: (  500/    saml)   Gid: (  501/    saml) : /home/saml/blog/vmware_networking_tutorial
Access: (0775/drwxrwxr-x)  Uid: (  500/    saml)   Gid: (  501/    saml) : /home/saml/blog
Access: (0700/drwx------)  Uid: (  500/    saml)   Gid: (  501/    saml) : /home/saml
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root) : /home
0

To check for a specific user, you can try the below.

sudo -u username namei path /long/path/to/file.txt

It will give you output as below if the user has access to the file.

f: /long/path/to/file.txt
d /
d long
d path
d to
- file.txt

Taking reference from https://serverfault.com/a/1139094/1104571

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.