Eu tenho um processo que é iniciado por um damon em execução como root, agora eu quero "rebaixar" os privilégios desse processo para os do usuário médio. Isso é possível? Se sim, como?
PS: rodando unix em um mac
Eu tenho um processo que é iniciado por um damon em execução como root, agora eu quero "rebaixar" os privilégios desse processo para os do usuário médio. Isso é possível? Se sim, como?
PS: rodando unix em um mac
Respostas:
O próprio processo deve chamar setuid (2). Você também deve investigar a execução dentro do chroot (8), se ainda não estiver. Até onde eu sei, não há como o root alterar o uid de outro processo.
Se o motivo de você executá-lo como raiz é vincular portas, sugiro executá-lo como um usuário normal em uma porta superior e usando o ipfw (8) no OS X para encaminhar a porta 80/443 / etc para a porta superior:
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
sozinho não é absolutamente suficiente.
sudo tcpdump -Z
usa initgroups (3), setgid (2) e setuid (2) para eliminar os privilégios de root de seu próprio processo.
# code taken from:
# http://www.opensource.apple.com/source/tcpdump/tcpdump-32/tcpdump/tcpdump.c
/* Drop root privileges and chroot if necessary */
static void
droproot(const char *username, const char *chroot_dir)
{
...
if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
fprintf(stderr, "tcpdump: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
username,
(unsigned long)pw->pw_uid,
(unsigned long)pw->pw_gid,
pcap_strerror(errno));
exit(1);
}
...
}
initgroups
, setgid
, setuid
(Finalmente!) É precisamente o paradigma direito sobre unix, e deve sempre ser seguido. Além disso, uma função responsável "droproot" verifica se seu uid e gid foram realmente configurados, mesmo que todas as três funções principais tenham retornado com êxito.
Você pode executar comandos como outros usuários usando su
:
su USERNAME -c COMMAND
Será executado COMMAND
com privilégios caiu para USER
.
Observe que, por padrão, su
usará o interpretador de shell do usuário de destino para executar o comando. Por outro lado, o comportamento padrão de sudo
é tratar o programa COMMAND
como independente, que é executado no ambiente atual. É claro que esses comportamentos padrão podem ser alterados com várias opções e variáveis de ambiente.
su
que não funcionará se USERNAME não tiver um shell definido (ou /bin/false
) enquanto o sudo funcionar.
su
refletirá isso. No entanto, sempre é possível substituir isso usando o -s
switch. Observe que o objetivo su
é imitar o comportamento de um determinado usuário - que normalmente é influenciado por seu shell. Por outro lado, sudo
(por padrão) ignoraria a configuração de shell do usuário de destino.
Para eliminar privilégios, você precisa de um usuário não raiz para o qual. Então é apenas uma questão de mudar para esse usuário:
#define UNPRIV_UID 48
#define UNPRIV_GID 48
if (getuid() == 0) { // we are root
// setting UID/GID requires root privileges, so if you don't set
// the GID first, you won't be able to do it at all.
if (setgid(UNPRIV_GID)!=0) die("Failed to set nonroot GID");
if (setuid(UNPRIV_UID)!=0) die("Failed to set nonroot UID");
}
ASSERT(getuid() != 0);
Observe que isso é feito dentro do próprio programa , e não em um script de wrapper. Muitos programas requerem privilégios de root para algum propósito específico (por exemplo, para vincular a uma porta de número baixo), mas não precisam de root depois disso. Portanto, esses programas serão iniciados como root, mas eliminarão os privilégios quando não forem mais necessários.
Se você não precisa de privilégios de root, simplesmente não o execute como root. Por exemplo:
# Change this:
myprog -C /my/config/file
# To this:
sudo -u someuser myprog -C /my/config/file
# Or this
su someuser -c "myprog -C /my/config/file"
setuid
função define apenas o UID efetivo , não o UID real. Você deve usar setreuid
se não quiser que o processo recupere os privilégios. (E o código acima não lida com privilégios suplementares grupo quer É adequado apenas para lançar código principalmente confiável..)
setuid()
define userids reais e salvos; você pode estar pensando seteuid()
. Nem todos os sistemas possuem setreuid()
, portanto, ele não pode ser usado em qualquer lugar. A semântica exata de setuid()
é complicada, mas se você tiver o euid 0, poderá eliminar todos os privilégios de identificação de usuário tradicionais setuid()
. A maior omissão nesta resposta é que initgroups
ou setgroups
deve ser chamada assim como setgid
e setuid
, e que afirmações mais completas devem ser feitas no final.
Se você estiver executando um executável diferente, ou seja, você está chamando execve
ou outro exec
membro da família de funções, talvez indiretamente através de uma função como system
or popen
, e o processo filho deve ser executado sem privilégios desde o início, a maneira mais simples é obter um shell envolvido e chamada su
. Aqui está uma visão geral de como o código pode parecer no Perl, mostrando as citações necessárias para:
$shell_command = quotemeta($path_to_executable) . " --option";
$shell_command =~ s/'/'\\''/; # protect single quotes for the use as argument to su
$su_command = sprintf("su -c '%s' %s", $shell_command, quotemeta($user_name));
open(PIPE, "$su_command |") or die;
Se o processo filho precisar iniciar como root, mas eliminar privilégios posteriormente, consulte o código nesta resposta , que ilustra como fazer o downgrade de privilégios em um processo.