Access Control Lists

Copyright © 2001 Conectiva S/A, (c) 2004 Elvis Pfützenreuter

1. Revisão das permissões Unix

Esta seção é uma revisão do sistema de permissões comum a todos os sistemas operacionais compatíveis com Unix.

1.1. Usuários e grupos

O Unix tem uma lista de usuários (em /etc/passwd) e uma lista de grupos (/etc/group). Cada usuário pertence a um grupo (este será seu grupo primario). Dentro de cada lista, não existe qualquer hierarquia entre usuários ou entre grupos Não há grupos de grupos, nem usuários-líderes.

Normalmente, é criado um grupo primário para cada usuário Unix, portanto as duas tabelas podem ficar bastante parecidas entre si. Mas não é necessário haver um grupo primário para cada usuário.

Cada usuário ainda pode ser incluído em outros grupos, que serão seus grupos secundários.

1.2. Arquivos

Cada arquivo tem alguns parâmetros de permissão:

O usuário-dono do arquivo não precisa necessariamente pertencer ao grupo-dono do arquivo. As permissões do grupo-dono na verdade regulam o que os usuários pertencentes àquele grupo poderão fazer com o arquivo.

Para ter as permissões do grupo-dono sobre o arquivo, um usuário precisa pertencer ao tal grupo. Mas não importa se é como grupo primário ou secundário; estando no grupo, tem as permissões.

Os "outros" usuários são todos os usuários que não o dono do arquivo e não pertencentes ao grupo-dono.

Os parâmetros de permissão possuem 3 bits cada um, com o seguinte significado:

rpermissão de leitura (bit mais significativo)
wpermissão de escrita
xpermissão de execução (para programas e scripts)

Para que, por exemplo, um usuário possa ler o arquivo, pelo menos uma das três condições a seguir deve ser atendida:

A manipulação das permissões em si é mais restrita; apenas o usuário-dono do arquivo pode mexer nas permissões do mesmo. (Isso também vale para os diretórios.)

As permissões especiais têm bits que potencializam a semântica dos anteriores:

Os bits acima têm propósito quase que totalmente restrito a binários.

os bits de permissão costumam ser representados por quatro números octais (visto que cada dígito octal corresponde exatamente a 3 bits).

Então, as permissões a seguir: SUID ativado, permissões do usuário "rwx", permissões do grupo "r-x", nenhuma permissão para outros, são representadas muito mais abreviadamente como 4750.

1.3. Diretórios

Os diretórios possuem exatamente os mesmos parâmetros de permissão dos arquivos, porém o significado dos bits de permissão mudam um pouco:

rpermissão de ler o diretório e consultar os diversos nomes de arquivos
wpermissão de gravar no diretório
xpermissão de abrir um arquivo deste diretório, se o programa já sabe o nome

O diretório contém o nome do arquivo e um ponteiro para o seu conteúdo no disco. Esse fato tem conseqüências sutis.

Para manipular um arquivo de nome conhecido, o usuário precisa ter permissão 'x' em cada um dos diretórios do caminho, além, é claro, das devidas permissões sobre o próprio arquivo (vide 1.2).

Para cada diretório do caminho, o usuário deve ser a) dono do diretório, b) pretencente ao grupo-dono, ou c) que o diretório tenha o bit 'x' setado para as permissões dos "outros" usuários. Por este motivo, um sem-número de diretórios padrão do Unix têm as permissões (root,root,0755).

Para listar nomes de arquivos de um diretório (é o que o comando 'ls' faz) o usuário precisa ter a permissão 'r' no diretório consultado.

Como geralmente a manipulação de um arquivo é precedida por uma busca, via de regra o usuário precisa ter pelo menos as permissões 'r' e 'x' em cada diretório do caminho para poder abrir um arquivo. Não por outra razão a permissão 0755 é a mais comum para diretórios...

Para CRIAR, RENOMEAR ou APAGAR um arquivo, o usuário precisa também ter permissão 'w' no diretório onde estiver o arquivo. Isso traz um paradoxo: é possível que um usuário possa gravar num arquivo sem poder apagá-lo ! Por outro lado, se o usuário tem apenas permissão de escrita sobre o diretório (e não sobre o arquivo), o usuário pode truncá-lo, visto que pode apagar o arquivo e criá-lo em seguida.

Para mudar as permissões de um arquivo, o usuário precisa ter apenas permissões de escrita sobre o arquivo, não sobre o diretório. Isso porque elas são gravadas no inode, não no diretório.

Em sistemas padrão POSIX, quando um usuário cria um novo arquivo em um diretório, o grupo-dono do mesmo é automaticamente setado para o grupo primário do usuário. (Eis o porquê da diferenciação entre grupo primário e secundários).

Já em sistemas BSD, o grupo-dono do novo arquivo será sempre o mesmo do diretório. Isso pode ser muito desejável para, por exemplo, garantir aos demais membros de um grupo o acesso ao novo arquivo.

Como essa característica do BSD é bastante desejável, o padrão POSIX também oferece esse recurso, como um opcional.

Os bits de permissões especiais também têm significado diferenciado:

1.4. umask

Um último recurso do sistema de permissões Unix é a máscara de bits denominada 'umask'. O objetivo do umask é impedir que o usuário, involuntariamente, crie arquivos com permissões excessivamente liberais.

O umask é um valor de 12 bits, que também costuma ser representado por três dígitos octais. Observe o seguinte exemplo, onde o usuário cria um arquivo com permissões bastante liberais (0666) porém seu umask é o padrão comumente adotado (0022):

        Especiais       Usuário         Grupo           Outros
        -------         -------         -------         -------
open	-  -  -         r  w  -         r  w  -         r  w  -  (0666)
umask	0  0  0         0  0  0         0  1  0         0  1  0  (0022)
----------------------------------------------------------------------------
final   -  -  -         r  w  -         r  -  -         r  -  -  (0644)

Como visto, os bits 1 do umask desligam incondicionalmente os respectivos bits da permissão final.

2. Porque as ACLs são necessárias

As permissões padrão Unix têm algumas limitações severas. Cada arquivo ou diretório pode pertencer a apenas um usuário e um grupo. E não existe um mecanismo suficientemente poderoso de herança de permissões.

As permissões Unix são eficientes (i.e. os processos de autenticação consomem o mínimo possível de CPU), e são suficientes para a configuração segura de um ambiente operacional.

Porém, as limitações supra citadas podem ser impeditivas na adoção do Unix como servidor de arquivos. Alguns dos "truques" das permissões Unix (SGID em diretórios, grupos secundários) mitigam as limitações em ambientes relativamente simples.

Num ambiente corporativo típico, temos pessoas organizadas em equipes. Também temos projetos ou tarefas. Normalmente, cada projeto terá um diretório ou pasta dentro de um servidor de arquivos. No mundo Unix, cada pessoa equivale a um usuário, e cada equipe equivale a um grupo.

Num mundo ideal, cada projeto seria manipulado unicamente por um usuário ou por um grupo, e nesse caso as permissões Unix seriam suficientes para controlar o acesso a cada projeto. Porém, é comum que cada projeto seja tocado concomitantemente por duas ou mais equipes, e eventualmente envolvendo funcionários avulsos de equipes esparsas. Também pode suceder de, por exemplo, a equipe A e B terem acesso de escrita aos arquivos do projeto, enquanto a equipe C teria apenas acesso de leitura (e obviamente acesso negado a quaisquer outros funcionários e grupos!).

Para tais situações, as permissões Unix são insuficientes pelo simples fato de que não se pode atribuir dois grupos-donos a um único diretório. Uma saída seria criar um grupo Unix por PROJETO, e incluir nesse grupo apenas os usuários que vão trabalhar no projeto. É uma saída possível, mas tem 3 desvantagens:

Ainda faltou mencionar a questão da herança de permissões. Supondo que o administrador consiga configurar permissões suficientemente boas para os diretórios, mas os arquivos ali criados terão permissões insuficientes.

3. ACLs POSIX e sua implementação no Linux

É IMPORTANTE QUE O LEITOR ENTENDA PERFEITAMENTE COMO FUNCIONAM AS PERMISSÕES UNIX COMUNS, VISTO QUE AS ACLs POSIX INTERAGEM DE FORMA RAZOAVELMENTE COMPLEXA COM AS MESMAS !!!

3.1. Usuários-donos e grupos-donos adicionais

A mais importante extensão das ACLs POSIX é a atribuição de usuários e grupos acicionais, com os respectivos bits de permissão (r, w e x). Observe os seguintes comandos: setfacl -m u:joao:rwx arquivo

Este comando atribui um usuário-dono adicional ao arquivo, com permissões de leitura, escrita e execução.

setfacl -m g:admin:r-x diretorio

Este atribui um grupo-dono adicional, com permissões de leitura (lembrar que o significado do bit 'x' é diferente para diretórios). Com estes poucos exemplos, já podemos formar algumas conclusões sobre as ACLs POSIX:

3.2. Consultando as ACLs de um arquivo

Na implementação Linux das ACLs POSIX, o comando 'ls' mostra um caractere '+' junto aos bits das permissões tradicionais, para indicar que aquele arquivo ou diretório tem uma ACL associada a ele:

/acl # ls -lsa
total 8
   1 drwxr-xr-x    8 epx      users        1024 Jun  8 21:49 .
   1 drwxr-xr-x   35 root     root         1024 Jun  7 23:13 ..
   1 drwxrwx---+   2 epx      users        1024 Jun  8 00:46 alpha
   1 drwxrwx---+   2 epx      users        1024 Jun  8 02:10 beta
   1 drwxrwx---+   2 epx      users        1024 Jun  8 00:19 delta
   1 drwxrwx---+   2 epx      users        1024 Jun  8 00:44 gama
   1 drwxrwx---+   2 root     root         1024 Jun  8 00:45 omega
   1 drwxrwx---    2 epx      users        1024 Jun  8 22:03 zeta

Da lista acima, apenas o subdiretório 'zeta' não tem ACLs. Para mostrar as ACLs em si, use o comando getfacl:

/acl # getfacl alpha
# file: alpha
# owner: epx
# group: users
user::rwx
group::r-x
group:admin:rwx
mask:rwx
other:---

O diretório 'alpha' tem uma ACL que garante ao grupo 'admin' acesso irrestrito ao diretório.

As linhas 'user::rwx' e 'group::r-x' referem-se ao usuário-dono e ao grupo-dono originais (epx:users).

3.3. Máscara de permissões ACL

No exemplo do comando 'getfacl', pode-se notar um registro denominado 'mask', que ainda não conhecíamos. Além disso, existe uma aparente discrepância. O comando 'ls' mostrou que os bits de permissão do grupo são 'rwx':

   1 drwxrwx---+   2 epx      users        1024 Jun  8 00:46 alpha

porém o comando getfacl disse que eram apenas 'r-x':

group::r-x

Num arquivo ou diretório que utilize ACLs (que tenha o '+' anexado às permissões tradicionais), os bits de permissão do grupo-dono tradicional mudam de significado. Ele atua como uma máscara para todas as demais permissões estendidas ACL, de forma análoga ao umask.

Para ilustrar a funcionalidade da máscara:

/acl # chmod 740 alpha
/acl # getfacl alpha
# file: alpha
# owner: epx
# group: users
user::rwx
group::r-x                      #effective:r--
group:admin:rwx                 #effective:r--
mask:r--
other:---

O comando 'chmod' alterou os bits de permissão do grupo-dono para 'r--'. Porém, o getfacl nos mostra que as permissões do grupo-dono continuam sendo 'r-x', e que a MÁSCARA é que foi mudada.

Note a presença do comentário '#effective:r--' para o grupo-dono original e o grupo adicional. Como a máscara é 'r--', as permissões do grupo-dono e de quaisquer outros usuários e grupos estendidos será, NO MÁXIMO, 'r--'. Essa mudança na semântica dos bits de permissão tradicionais é um pouco 'chata' de entender, mas tem sua razão de existir.

Visto que os bits da máscara podem ser manipulados por um simples 'chmod', o usuário-dono do arquivo pode limitar, de forma simples e rápida, revogar todas as permissões estendidas das ACLs sem alterá-las. Com um simples

chmod 700 arquivo

o usuário-dono pode desativar todas as ACLs, e ativá-las novamente quando quiser usando

chmod 770 arquivo

A máscara também pode ser alterada de forma mais elegante com o próprio setfacl:

setfacl -m m:rwx arquivo

3.4. Utilizando setfacl para alterar as permissões tradicionais

Os bits de permissão do grupo-dono original não podem mais ser alterados via 'chmod', por força do exposto no tópico 3.3. Mas podemos usar o próprio setfacl para isso:

setfacl u::rwx arquivo      # usuário-dono
setfacl g::rwx arquivo      # grupo-dono
setfacl o::rwx arquivo      # outros usuários quaisquer

A alteração do usuário-dono e do grupo-dono em si continua sendo feita pelos comandos tradicionais 'chmod' e 'chgrp'.

3.5. Permissões default

Uma das limitações do sistema de permissões tradicional Unix é a falta de um mecanismo de herança de permissões. Veremos agora como fazer isso usando ACLs POSIX:

/acl # getfacl delta
# file: delta
# owner: epx
# group: users
user::rwx
group::r-x
group:admin:r-x
group:doc:rwx
mask:rwx
other:---

/acl # setfacl -m d:u::rwx delta
/acl # setfacl -m d:g::r-x delta
/acl # setfacl -m d:o:--- delta
/acl # setfacl -m d:g:admin:r-x delta
/acl # setfacl -m d:g:doc:rwx delta
/acl # setfacl -m d:m:rwx delta

/acl # getfacl delta
# file: delta
# owner: epx
# group: users
user::rwx
group::r-x
group:admin:r-x
group:doc:rwx
mask:rwx
other:---
default:user::rwx
default:group::r-x
default:group:admin:r-x
default:group:doc:rwx
default:mask:rwx
default:other:---

Usando o prefixo 'd:', atribuimos as permissões ACL 'default', ao invés das próprias permissões do arquivo/diretório. Essas permissões é que serão herdadas pelos arquivos criados dentro do diretório:

/acl # touch delta/arqv
/acl # getfacl delta/arqv
# file: delta/arqv
# owner: root
# group: root
user::rw-
group::r-x                      #effective:r--
group:admin:r-x                 #effective:r--
group:doc:rwx                   #effective:rw-
mask:rw-
other:---

A presença das ACLs 'default' mitiga a importância do umask, e de fato o umask é desconsiderado de todo, na criação de arquivos dentro de diretórios com ACLs default.

Também é oportuno lembrar que:

- As ACLs default não precisam de forma alguma coincidir com as ACLs do diretório em si. (Embora a suprema maioria das aplicações práticas imponha que umas e outras sejam iguais).

- Obviamente, apenas diretórios podem ter ACLs default.

- Os subdiretórios herdarão também as próprias ACLs default do diretório-pai, e com isso o mecanismo de herança fica completo.

- Note, no primeiro exemplo, que definimos a máscara default como d:m:rwx, mas o arquivo final 'delta/arqv' ficou com uma máscara 'rw'. O bit de execução é desligado incondicionalmente. Porém, os diretórios herdarão a máscara completa ('rwx'), visto que o bit 'x' tem significado diferente para diretórios (e via de regra é necessário que 'x' esteja sempre ativado nos mesmos).

3.6. Sintaxe completa dos comandos setfacl e getfacl

3.6.1. Permissões

Algumas das formas aceitas já foram vistas nos exemplos. Segue algumas dicas adicionais.

Podemos especificar as permissões usando uma forma mais extensa e elegante:

d:u::rwx	-> 	default:user::rwx
g:admin:r-x	->	group:admin:r-x
o:r--		->	other:r--
m:rwx		->	mask:rwx

Ao invés de nomes de usuários e grupos, podemos usar os respectivos números.

Pode-se concatenar vários registros, com vírgulas, em um único comando:

setfacl -m u::rwx,g::r-x,o:---,u:joao:r-- arquivo

Se você quer alterar um registro da ACL de um arquivo, basta especificar um registro que coincida com o preexistente. Também, é possível usar os modificadores '+' (mais) e '^' (menos), para ligar e desligar determinados bits da permissão. O exemplo a seguir desliga o bit 'w' para o grupo 'doc':

/acl # setfacl -m group:doc:^w delta

Os bits de permissão também podem ser especificadas como um dígito octal.

3.6.2. Parâmetros para o comando setfacl

-m	Se o registro especificado já existir, os bits de permissão
	especificados serão atualizados. Se o registro ainda não existir,
	será adicionado à ACL.

-s	Configura a ACL. Quaisquer registros anteriores serão eliminados e
	substituídos pelos novos. Para a formação incremental da ACL, o 
	parâmetro -m é mais indicado. Exemplo:

setfacl -s u:epx:rwx,u:joao:r-x,g:admin:rx arquivo

-x	Elimina o registro especificado, como no exemplo:

setfacl -x g:admin arquivo

-M/S/X	Com significado idêntico aos respectivos parâmetros de letra minúscula,
	porém os registros são lidos de um arquivo (especificado logo depois
	deste parâmetro). O formato exigido é exatamente o formato gerado pelo 
	comando getfacl. Para ler da entrada padrão, use o traço ('-'). 
	Exemplos:

getfacl arquivo1 > /tmp/acltemp
cat /tmp/acltemp | setfacl -S- arquivo2  	# opção 1
setfacl -S /tmp/acltemp arquivo2		# opção 2

Note que setfacl não usou o nome de arquivo contido em /tmp/acltemp. Se isso for necessário, a opção '-B' é que deve ser usada.

-b 	Remove todos os registros ACL do arquivo. Exemplo:

setfacl -b arquivo

-k	Remove apenas os registros ACL 'default' do diretório.

-d	Todas as operações com registros ACL referir-se-ão aos registros
	'default'.

-B	Restaura uma cópia de segurança gerada pelo comando 'getfacl -R' ou
	similar. (Vide getfacl)

-t	Modo de teste. Apenas testa a sintaxe mas não faz nenhuma alteração
	'quente'.

-R	Aplica a operação a todos os arquivos e subdiretórios recursivamente.
	(Esta opcão NÃO pode ser usada em conjunto com -B)

-5	Idêntico a -R, mas processa os arquivos primeiro, antes dos respectivos
	subdiretórios.

Outros parâmetros menos usados podem ser encontrados na página 'man' do comando setfacl.

3.6.3. Parâmetros do comango getfacl

Além das formas óbvias de uso, que já foram abordadas nos exemplos, podem ser utilizados os seguintes parâmetros:

-A	Mostra apenas os registros ACL do arquivo em si

-d	Oposto de '-d', mostra apenas os registros 'default', e não mostra
	o prefixo 'default:' na saída.

-a	Em listas recursivas, mostra também as ACLs de arquivos cujos nomes
	comecem com ponto (que normalmente são ocultados).

-c	Não mostra as linhas de comentário

-e	Mostra os comentários com as permissões efetivas, mesmo as que não
	foram prejudicadas pela máscara.

-E	Oposto de '-e', não mostra comentários sobre permissões efetivas mesmo
	que haja permissões prejudicadas pela máscara.

-s 	Pula arquivos que não tenham registros ACL.

-R 	Lista as ACLs de todos os arquivos e subdiretórios recursivamente.
	Exemplo:

cd /acl
getfacl -sR . > copia-de-seguranca
# depois de uma reformatação...
mkdir /acl
cd /acl
setfacl -B copia-de-segurança

-Y 	Segue links simbólicos. (O padrão é não seguí-los.)

-5	Idem '-R', mas imprime primeiro as permissões dos arquivos.

-P	Imprime caminhos absolutos (precedidos com '/'). O padrão é suprimir
	a barra de prefixo, para que a lista de ACLs possa ser reaplicada
	facilmente em uma outra árvore de diretórios.

-	Lê a lista de arquivos a partir da entrada padrão.

--	Fim dos parâmetros. Os parâmetros à direita deste serão interpretados
	como nomes de arquivo mesmo que comecem com traço.

3.7. Implementação no Linux

As ACLs POSIX são suportadas nativamente no Linux no kernel 2.6. As distribuições mais novas, que já trazem essa versão de kernel, têm suporte direto a ACL.

Como outros programas, além do kernel, precisam ser atualizados para o suporte a ACLs, aconselha-se a usar distribuições com suporte a ACL ao invés de tentar incluir esse suporte manualmente.

4. Comparação com outros tipos de ACL

Novell/Windows NT POSIX tradicional ACLs POSIX
As permissões são armazenadas "separadamente" do sistema de arquivos, e estão centradas nos usuários e grupos. As permissões são centradas em arquivos e diretórios. Cada arquivo sabe que usuários/grupos podem acessá-lo. As ACLs são armazenadas no sistema de arquivos. Idem POSIX.
Um grupo pode herdar permissões de outro(s) grupo(s) e/ou de outro(s) usuário(s), além de é claro ter as suas próprias permissões. Não é possível estabelecer hierarquia entre grupos em sistemas POSIX, muito menos grupos hierarquicamente dependentes de usuários. Idem POSIX.
Um usuário pode herdar permissões de outro(s) usuário(s), isso de forma concomitante à herança de permissões de um ou mais grupos. Usuários podem pertencer a um ou mais grupos, e portanto ter as mesmas permissões deles. Mas não se pode, por exemplo, fazer com que 'usuário A é equivalente a B'. Idem POSIX.
Quaisquer permissões atribuídas a um diretório são automaticamente válidas para todos os arquivos e subdiretórios contidos nele. Cada arquivo e diretório tem suas próprias permissões, com herança muito limitada. Cada arquivo e diretório têm sua própria ACL. A transmissão de permissões é possível, mas tem de ser explicitamente solicitada, e atuará apenas sobre arquivos criados dali para diante.
Em extensão ao item anterior, as permissões atribuídas a um subdiretório atuarão cumulativamente às permissões estabelecidas em diretórios de nível mais alto. Cada arquivo e diretório têm sua própria ACL, que não se acumula de nenhuma forma com as ACLs dos diretórios do caminho. Idem POSIX tradicional.
As permissões de 'renomear' e 'apagar' são atribuíveis ao próprio arquivo, e independem das permissões que o usuário tenha no diretório. O usuário precisa ter permissão de escrita no diretório do arquivo para poder renomear e apagar arquivos. Idem POSIX tradicional.
Uma modificação de permissão tem efeito imediato sobre os usuários. A semântica UNIX verifica as permissões no momento de abertura do arquivo. Uma vez aberto o arquivo, o programa retém as permissões até fechá-lo, mesmo que o administrador do sistema torne a ACL mais restritiva nesse interim. Idem POSIX tradicional.
É possível criar diretórios 'write-only' ou 'ratoeiras', onde o usuário possa jogar arquivos mas nunca mais lê-los ou apagá-los. (Dica de andreas@conectiva.com.br) Não é possível criar diretórios-ratoeiras perfeitos, visto que para criar um arquivo, o usuário precisa ter direitos de gravação e de varredura ('x'), e esta última permissão implica em que o usuário ainda possa abrir ou apagar o arquivo se souber seu nome completo. Idem POSIX tradicional.