Comment vérifier si un utilisateur peut accéder à un fichier donné?

60

Les autorisations des utilisateurs * nix sont très simples, mais les choses peuvent devenir désordonnées lorsque vous devez prendre en compte tous les accès au répertoire parent avant d’atteindre un fichier donné. Comment puis-je vérifier si l'utilisateur a suffisamment de privilèges? Si non, alors quel répertoire refuse l'accès?

Par exemple, supposons un utilisateur joeet le fichier /long/path/to/file.txt. Même si a file.txtété chmodé à 777, joe doit toujours pouvoir accéder /long/, et alors /long/path/et puis /long/path/to/avant. Ce dont j'ai besoin, c'est d'un moyen de vérifier automatiquement cela. Si joen'a pas accès, je voudrais aussi savoir où il a été refusé. Peut-être qu'il peut accéder /long/, mais pas /long/path/.

Metalcoder
la source

Réponses:

71

Vous pouvez utiliser

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

qui va sortir toutes les autorisations dans le chemin dans une liste verticale.

ou

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

pour lister tous les propriétaires et les permissions

exussum
la source
2
Cela devrait être la bonne réponse. En fait, utiliser namei <path> || exit 1vous permet de détecter très facilement un problème d’autorisation dans un script.
lorenzog
5
il ne répond pas directement si joe a accès au fichier.
JFS
15

Vous pouvez utiliser bash pour faire cela.

$ 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

Pour vérifier cela pour un utilisateur spécifique, vous pouvez utiliser sudo.

sudo -u joe ./check-permissions.sh /long/path/to/file.txt

la source
sudo -u joe script. Ici le script est le nom du fichier de script non? alors tu dis à sudo d'agir comme si joe appelait le script?
tgkprog
Précisément. J'ai modifié ma réponse pour clarifier cela.
J'ai légèrement modifié mon script pour gérer les chemins non absolus.
@EvanTeitelman Avec un chemin absolu, aviez-vous l'intention d'initialiser pathpour être vide? ou /?
Gilles 'SO- arrête d'être méchant'
@ Gilles: Je voulais dire que ce soit vide. Dans l'exemple, pathest défini sur /longla première fois autour de la boucle, ce qui est correct. Devrais-je régler pathsur rien explicitement ( path=)? Merci également de simplifier mon utilisation de tr.
3

Comme je l’ai compris dans votre question, vous devriez le vérifier pour différents utilisateurs (pas seulement joe), alors dans ce cas, le moyen le plus simple est de le vérifier de manière récursive via sudo comme ceci:

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
se ruer
la source
Joe a besoin d'autorisations d'exécution sur les répertoires, pas d'autorisations de lecture.
@ EvanTeitelman oui, vous avez raison. Fixé.
Rush
@rush J'ai essayé de le tester en utilisant le fichier suivant: /root/test/test.txt (autorisations sont 0755, 0700et 0777). J'ai publié ./script.sh /root/test/test.txt joeet cela a fait écho original file /root/test/test.txt is readable for joe. Aussi, en essayant cela, j'ai mal saisi le test dir:, ./script.sh /root/tst/test.txt joeet il a fait écho original file /root/tst/test.txt is readable for joe. Ai-je raté quelque chose?
Metalcoder
@Metalcoder désolé, c'est de ma faute. Il y avait une exclamation supplémentaire. Il est supprimé maintenant, vous pouvez l'essayer une fois de plus, cela devrait fonctionner correctement maintenant.
Rush
@rush cela a fonctionné! Cette exclamation supplémentaire annule le résultat de -r $FILE, non?
Metalcoder
1

Voici ma tentative de fournir cette fonctionnalité. J'ai choisi d'utiliser stat, une whileboucle et dirname.

J'ai créé ce 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

Vous le lancez comme ça:

$ 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
slm
la source