Um arquivo
sudoers é composto por dois tipos de entradas:
- O primeiro grupo é chamado de aliases, basicamente são variáveis.
- O segundo grupo de entradas são especificações de usuário (user specifications), que definem quem pode executar o quê.
Quando múltiplas entradas combinam para um usuário, elas são aplicadas na ordem de declaração.
Se há múltiplas entradas, então a última é a que será utilizada. Isso pode significar que a combinação final não é a mais específica possível. A gramática em sudoers é descrita na forma EBNF - Extended Backus-Naur Form. (vide a página da Wikipédia para mais informações sobre EBNF).
Guia Rápido para EBNF
EBNF é um modo conciso e exato de descrever a gramática de uma linguagem. Cada definição EBNF é baseada em regras de produção (?). Por exemplo:
symbol ::= definition | alternate1 | alternate2 | ...
Cada regra de produção faz referência a outras, e juntas fazem a gramática da linguagem.
EBNF possui operadores, que alguns leitores podem reconhecer como operadores de expressões regulares. Não interprete esses caracteres como wildcards, pois eles não são. Wildcards existem em EBNF com uma sintaxe totalmente diferente.
( ? ) - Esse sinal define que o símbolo precedente (ou um grupo deles) é opcional. Isso significa que ele pode aparecer uma vez, mas não em todas as definições.
( * ) - Esse sinal define que o símbolo precedente (ou um grupo deles) pode aparecer zero ou mais vezes em uma definição.
( + ) - Esse sinal define que o símbolo precedente (ou um grupo deles) pode aparecer uma ou mais vezes. Parêntesis podem ser utilizados para manter esses símbolos juntos. O uso de aspas simples permite identificar uma cadeia de caracteres (string) em oposição ao nome de um símbolo.
Aliases
Existem quatro tipos de aliases: User_Alias, Runas_Alias, Host_Alias e Cmnd_Alias.
Um alias possui o seguinte formato genérico:
Alias_Type NAME = item1,item2, ...
Onde Alias_Type é um dos quatro tipos disponíveis. Um NAME é uma cadeia de caracteres [a-z][A-Z], números [0-9] e o traço baixo (underscore). Um NAME DEVE começar com uma letra maiúscula.
Por convenção, todas são escritas em maiúsculas para facilitar a leitura do código por humanos. É possível declarar diversos alias na mesma declaração de tipo. Isso pode ser feito na mesma linha, separando cada item por dois pontos ( : ), por exemplo:
Alias_Type NAME = item1, item2, item3 : NAME = item4, item5
A definição EBNF do que constituí um membro válido de um alias é:
Uma User_List é constituída por um ou mais nomes de usuário ( User ), por valores numéricos de UID (prefixados com #, pode ser exigido um caractere de escape em alguns sistemas), nomes de grupos de sistema e IDs (prefixados com ( % ) e ( %# ) respectivamente), grupos de rede (sic, netgroups) (prefixados com ( + ), nomes de grupos não-Unix e seus IDs (prefixados com ( %: ) e ( %:# ) respectivamente) e User_Aliases. Cada item da lista pode ser prefixado com zero ou mais operadores ( ! ). Um número ímpar de operadores ( ! ) nega o valor do item; um número par de negações apenas cancela a negação anterior. (São operadores lógicos de negação).
Um nome de usuário, UID, nome de grupo, GID, grupo de rede, grupo não-Unix ou GID não-Unix podem ser fechados entre aspas duplas para evitar a necessidade escapar alguns caracteres especiais.
Alternativamente, caracteres especiais podem ser especificados em modo hexadecimal escapado (por exemplo, \x20 para um espaço em branco). Quando utilizar aspas duplas, qualquer caractere prefixado deve ser inserido dentro de aspas.
A sintaxe atual de nounix_group e nounix_gid depende do provedor do plug-in. Por exemplo, o plug-in QAS AD suporta os seguintes formatos:
- Grupo no mesmo domínio: "%:Group Name"
- Grupo em qualquer domínio: "%:Group Name@FQDN"
- Grupo SID: "%:S-1-2-34-5678901234-5678901234-5678901234-567"
Veja "Plug-ins provedores de Grupos" para mais informações. Observe que as aspas entorno dos nomes de grupos são opcionais.
Cadeias de caracteres não-limitadas por aspas devem usar uma barra invertida (backslash) para escapar espaços e caracteres especiais.
Veja "Outros caracteres especiais e palavras reservadas" para uma lista dos caracteres que PRECISAM ser escapados.
Uma Runas_List é similar a uma User_List, exceto que em vez de conter User_Aliases ele contém Runas_Aliases.
Observe que os nomes de usuário e de grupo são combinados como cadeias de caracteres (strings). Em outras palavras, dois usuários (ou grupos) com o mesmo UID (ou GID) são considerados distintos. Se você deseja combinar todos os nomes de usuário com o mesmo UID (por exemplo, no BSD o root e o toor), então deve usar um único UID - #0 - como argumento.
Uma Host_List é composta de um ou mais nomes de host, endereço IP, número de rede, grupo de rede (netgroups, prefixado com ( + )) ou outros aliases.
Novamente, o valor de um item pode ser negado com o operador de negação ( ! ).
Se você não deseja especificar uma máscara de rede juntamente com o número da rede, SUDO irá consultar cada um dos hosts da rede local e, se o número da rede corresponder a um destes hosts, então a máscara correspondente será utilizada.
A máscara de rede pode ser especificada em seu formato decimal (255.255.255.255) ou no formato hexadecimal (ffff:ffff:ffff:ffff), ou ainda na notação CIDR (representando o número de bits da máscara, por exemplo: 8, 16 ou 24).
Um nome de host pode incluir wildcards no estilo do shell (consulte a seção wildcards), a menos que o comando hostname retorne um fqdn (depende do sistema operacional) não é necessário usar fqdn no wildcard.
Observe que SUDO somente inspeciona as interfaces de rede atuais, isso significa que localhost (127.0.0.1) NUNCA combina. Além disto, o nome de host como localhost somente combina se esse for o nome do host (o que de fato nunca deve ocorrer, pois atualmente até sistemas fora da rede devem usar nomes de hosts).
Uma Cmnd_List é uma lista com um ou mais nomes de comandos, diretórios e outros aliases.
Um nome de comando é um nome totalmente qualificado, que pode incluir wildcards no estilo do shell.
Um nome simples de arquivo permite ao usuário executar o comando com quaisquer argumentos que desejar. Entretanto, você pode especificar um comando como uma linha contendo os argumentos (incluindo wildcards). Alternativamente, você pode especificar ( "") para indicar que o comando SOMENTE pode ser executado sem argumentos.
Um diretório é um nome totalmente qualificado de um caminho, que termina com um caractere de barra ( / ). Quando especificar um diretório em uma Cmnd_List, o usuário será capaz de executar qualquer arquivo nesse diretório (observe que a permissão não é passada por herança para os subdiretórios desse diretório).
Se um Cmnd for associado a uma linha com argumentos, então os argumentos na Cmnd devem combinar exatamente aos valores indicados pelo usuário na linha de comando ( ou combinar a partir de wildcards, se houver ).
Observe que os seguintes caracteres ( vírgula (,) dois-pontos (:) igualdade (=) barra invertida (\) ) DEVEM ser escapados com uma barra invertida se eles forem utilizados como argumentos de linha de comando.
O comando sudoedit é utilizado para permitir ao usuário editar arquivos com sudo. Isso pode exigir o uso de vários argumentos de modo similar a quando editamos em linha de comando. Observe que sudoedit é um built-in, isso significa que esse comando está "dentro" de sudo. Desta forma, mesmo sudo deve ser declarado em sudoers.
Se um nome de comando é prefixado com uma Digest_Spec, o comando somente irá combinar com sucesso se ele puder ser verificado usando um método de Digest como SHA-2. Isso é útil em situações onde o usuário invocando sudo tem permissão de escrita para o comando ou para o diretório pai.
As seguintes formas de Digest são suportadas por sudo: sha224, sha256, sha384 e sha512. Uma cadeia de caracteres pode ser especificada em hexadecimal ou no formato base 64 (mais compacto). Existem diversos utilitários capazes de gerar um hash SHA-2 nesses formatos, por exemplo openssl, shasum, sha224sum, sha256sum, sha384sum, sha512sum.
O exemplo a seguir usa openssl para para gerar uma saída em sha224 e o exemplo seguinte em base 64.
sha224:
openssl dgst -sha224 /bin/ls
SHA224(/bin/ls)= 118187da8364d490b4a7debbf483004e8f3e053ec954309de2c41a25
base 64:
openssl dgst -binary -sha224 /bin/ls | openssl base64
EYGH2oNk1JC0p9679IMATo8+BT7JVDCd4sQaJQ==
O uso de Digest para checar comando foi introduzido na versão 1.8.7 de sudo.
Continua na parte III...
Referências:
[1] -
http://www.sudo.ws/man/1.8.12/sudoers.man.html