Como verificar se um usuário pode acessar um determinado arquivo?

60

As permissões de usuário do * nix são realmente simples, mas as coisas podem ficar complicadas quando você precisa levar em consideração todo o acesso ao diretório pai antes de chegar a um determinado arquivo. Como posso verificar se o usuário tem privilégios suficientes? Caso contrário, qual diretório está negando acesso?

Por exemplo, suponha um usuário joee o arquivo /long/path/to/file.txt. Mesmo que tenha file.txtsido modificado para 777, joe ainda precisa ser capaz de acessar /long/, e depois /long/path/e depois /long/path/to/antes. O que eu preciso é uma maneira de verificar isso automaticamente. Se joenão tiver acesso, também gostaria de saber onde ele foi negado. Talvez ele possa acessar /long/, mas não /long/path/.

Metalcoder
fonte

Respostas:

71

Você pode usar

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

que produzirá todas as permissões no caminho em uma lista vertical.

ou

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

listar todos os proprietários e as permissões

exussum
fonte
2
Essa deve ser a resposta certa. De fato, o uso namei <path> || exit 1permite detectar um problema de permissão com muita facilidade em um script.
Lorenzog
5
não responde diretamente se joe tem acesso ao arquivo.
jfs
15

Você pode usar o bash para fazer isso.

$ 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 isso para um usuário específico, você pode usar sudo.

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

fonte
script sudo -u joe. Aqui script é o nome do arquivo de script, certo? então o seu dizer ao sudo para agir como Joe estava chamando o script?
Tgkprog 09/07/2013
Precisamente. Modifiquei minha resposta para esclarecer isso.
Fiz uma pequena modificação no meu script para lidar com caminhos não absolutos.
@EvanTeitelman Com um caminho absoluto, você queria inicializar pathpara estar vazio? ou /?
Gilles 'SO- stop be evil'
@ Gilles: eu pretendia que ele estivesse vazio. No exemplo, pathestá definido para /longa primeira vez no loop, o que está correto. Devo definir pathnada explicitamente ( path=)? Além disso, obrigado por simplificar meu uso de tr.
3

Como recebi da sua pergunta, você deve checá-la para diferentes usuários (não apenas joe); nesse caso, a maneira mais fácil é checá-la recursivamente via sudo desta maneira:

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
pressa
fonte
Joe precisa executar permissões nos diretórios, não permissões de leitura.
@EvanTeitelman sim, você está certo. Fixo.
corrida
@rush Tentei testá-lo usando o seguinte arquivo: /root/test/test.txt (permissões são 0755, 0700e 0777). Eu emiti ./script.sh /root/test/test.txt joee ecoou original file /root/test/test.txt is readable for joe. Além disso, ao tentar isso, digitei errado o diretório de teste:, ./script.sh /root/tst/test.txt joee ecoou original file /root/tst/test.txt is readable for joe. Perdi alguma coisa?
Metalcoder
@ Metalcoder desculpe, a culpa é minha. Houve uma exclamação extra. Ele foi removido agora, você pode tentar mais uma vez, deve funcionar bem agora.
corrida
@rush funcionou! Essa exclamação extra nega o resultado -r $FILE, certo?
Metalcoder
1

Aqui está minha tentativa de fornecer essa funcionalidade. Optei por usar stat, um whileloop e dirname.

Eu criei 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

Você executa da seguinte maneira:

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