¿Cómo verificar si un usuario puede acceder a un archivo determinado?

60

* Los permisos de usuario de nix son realmente simples, pero las cosas pueden complicarse cuando tienes que tener en cuenta todo el acceso al directorio principal antes de llegar a un archivo determinado. ¿Cómo puedo verificar si el usuario tiene suficientes privilegios? Si no, ¿qué directorio está negando el acceso?

Por ejemplo, suponga un usuario joey el archivo /long/path/to/file.txt. Incluso si file.txtfue modelado a 777, Joe todavía tiene que poder acceder /long/, y luego /long/path/y /long/path/to/antes. Lo que necesito es una forma de verificar esto automáticamente. Si joeno tiene acceso, también me gustaría saber dónde se le ha denegado. Quizás él pueda acceder /long/, pero no /long/path/.

Codificador de metal
fuente

Respuestas:

71

Puedes usar

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

que generará todos los permisos en la ruta en una lista vertical.

o

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

para enumerar todos los propietarios y los permisos

exussum
fuente
2
Esta debería ser la respuesta correcta. De hecho, el uso le namei <path> || exit 1permite detectar un problema de permisos con mucha facilidad en un script.
lorenzog
55
no responde directamente si joe tiene acceso al archivo.
jfs
15

Puedes usar bash para hacer esto.

$ 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

Para verificar esto para un usuario específico, puede usar sudo.

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

fuente
sudo -u joe script. Aquí script es el nombre del archivo de script ¿verdad? Entonces, ¿le estás diciendo a sudo que actúe como Joe estaba llamando al guión?
tgkprog
Precisamente. He modificado mi respuesta para aclarar eso.
Hice una ligera modificación en mi script para manejar rutas no absolutas.
@EvanTeitelman Con una ruta absoluta, ¿querías inicializar pathpara estar vacío? o /?
Gilles 'SO- deja de ser malvado'
@Gilles: quise decir que estuviera vacío. En el ejemplo, pathse establece por /longprimera vez alrededor del ciclo, lo cual es correcto. ¿Debo establecer pathnada explícitamente ( path=)? Además, gracias por simplificar mi uso de tr.
3

Como obtuve de su pregunta, debe verificarlo para diferentes usuarios (no solo Joe), por lo que en ese caso la forma más fácil es verificarlo de manera recursiva a través de sudo de esta manera:

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

uso:

./script.sh /long/path/to/file.txt joe
prisa
fuente
Joe necesita ejecutar permisos en los directorios, no leer permisos.
@EvanTeitelman sí, tienes razón. Fijo.
prisa el
@rush intenté probarlo utilizando el siguiente archivo: /root/test/test.txt (permisos son 0755, 0700y 0777). Emití ./script.sh /root/test/test.txt joey se hizo eco original file /root/test/test.txt is readable for joe. Además, al intentar esto, escribí mal el directorio de prueba: ./script.sh /root/tst/test.txt joey se hizo eco original file /root/tst/test.txt is readable for joe. ¿Me perdí algo?
Metalcoder
@Metalcoder lo siento, es mi culpa. Hubo una exclamación extra. Se ha eliminado ahora, puedes probarlo una vez más, debería funcionar bien ahora.
prisa el
@ Rush funcionó! Esa exclamación adicional niega el resultado de -r $FILE, ¿verdad?
Metalcoder
1

Aquí está mi intento de proporcionar esta funcionalidad. He optado por usar stat, un whilebucle, y dirname.

He creado este 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

Lo ejecutas así:

$ 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
fuente