Existem pelo menos 3 maneiras pelas quais pode ser perigoso:
-
Se
/etc/sudoers
não terminar em um caractere de nova linha (quesudo
evisudo
allow), por exemplo, se ele terminar em uma linha#includedir /etc/sudoers.d
não finalizada, seu comando fará:#includedir /etc/sudoers.dDefaults insults
que irá quebrá-lo e tornar
sudo
inutilizável. -
echo
pode falhar ao gravar a string completa, por exemplo, se o sistema de arquivos estiver cheio. Por exemplo, pode ser capaz de escreverDefaults in
. Que novamente irá quebrar o seu arquivosudoers
. - Em uma máquina com vários administradores, se ambos tentarem modificar
/etc/sudoers
ao mesmo tempo, os dados que eles escreverem poderão ficar entrelaçados.
visudo
evita esses problemas porque permite que você edite um arquivo temporário ( /etc/sudoers.tmp
), detecta se o arquivo foi modificado (infelizmente não se o arquivo foi com sucesso modificado como não funciona) t parece estar verificando o status de saída do editor), verifica a sintaxe e executa uma rename
(uma operação atômica) para mover o novo arquivo no lugar. Portanto, ele atualizará com êxito o arquivo (desde que seu editor também deixe o arquivo não modificado se falhar em gravar o novo) ou falhe se não puder ou a sintaxe for inválida.
visudo
também protege contra várias pessoas que editam os arquivos sudoers
ao mesmo tempo.
Agora, confiantemente usando visudo
de maneira automática também é complicado. Existem vários problemas com isso:
- Você pode especificar um comando do editor para
visudo
com a variável de ambienteVISUAL
(tem precedência sobreEDITOR
), mas somente se a opçãoenv_editor
não tiver sido desativada. - minha versão de
visudo
, pelo menos, sob algumas condições, edita todos os/etc/sudoers
e todos os arquivos incluídos (executa$VISUAL
para todos eles). Portanto, você precisa garantir que seu$VISUAL
apenas modifique/etc/sudoers
. - como visto acima, não verifica o status de saída do editor. Portanto, você precisa ter certeza de que o arquivo que seu editor salva seja gravado com sucesso ou não tenha sido modificado.
- Ele avisa o usuário em caso de problema.
Enfrentar tudo isso é um pouco complicado. Veja como você pode fazer isso:
NEW_TEXT='Defaults insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
umask 077
{
cat /etc/sudoers.tmp && printf "\n%s\n" "$NEW_TEXT"
} > /etc/sudoers.tmp.tmp &&
mv -f /etc/sudoers.tmp.tmp /etc/sudoers.tmp
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null
Não funcionará se env_editor
não estiver definido.
Em um sistema GNU, uma alternativa melhor seria usar sed -i
, o que deve deixar sudoers.tmp
não modificada se falhar em gravar a versão mais recente:
Adicione insults
:
SED_CODE='
/^[[:blank:]]*Defaults.*insults/,${
/^[[:blank:]]*Default/s/!*\(insults\)//g
$q
}
$a\Defaults insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
sed -i -- "$SED_CODE" "$2"
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null
Remova insultos:
SED_CODE='
/^[[:blank:]]*Defaults.*insults/,${
/^[[:blank:]]*Defaults/s/!*\(insults\)/!/g
$q
}
$a\Defaults !insults' \
CODE='
if [ "$2" = /etc/sudoers.tmp ]; then
printf >&2 "Editing %s\n" "$2"
sed -i -- "$SED_CODE" "$2"
else
printf >&2 "Skipping %s\n" "$2"
fi' \
VISUAL='sh -fc IFS=:;$1 sh eval:eval:"$CODE"' visudo < /dev/null