Os identificadores (ou IDs) do usuário real e efetivo são obtidos com a ajuda das chamadas de sistema getuid() e geteuid().
#include <unistd.h> #include <sys/types.h> uid_t getuid(void) /* determina o ID do usuário real */ uid_t geteuid(void) /* determina o ID do usuário efetivo */
Valor de retorno: identificador real ou efetivo. Não existe erro possível neste caso.
Estes identificadores podem ser modificados pela chamada de sistema setuid().
#include <unistd.h> #include <sys/types.h> int setuid(uid_t uid) /* muda o ID do usuário */ uid_t uid /* novo valor do ID */
Valor de retorno: -1 em caso de erro.
Além disso, a utilização das primitivas implicam no salvamento (backup) do identificador precedente. A gestão de setuid() é definida pelas três regras:
O exemplo a seguir tenta esclarecer as dúvidas relativas ao assunto:
O código foi escrito e compilado sobre o login saibel, com os IDs real e ID efetivo valendo 1198.
O programa é lançado sucessivamente da conta saibel, e após da conta usertest (ID real e ID efetivo valendo).
/* arquivo test_uid.c */ #include <errno.h> #include <stdio.h> #include <stdlib.h> /* primitiva system */ #include <unistd.h> #include <sys/types.h> int main() { system("echo Meu login e: $LOGNAME"); printf("Meu user id real e: %d\n",getuid()) ; printf("Meu user id efetivo e: %d\n",geteuid()) ; if (setuid(4010) == -1) { perror("Error setuid()") ; exit(-1) ; } printf("Meu user id real : %d\n",getuid()) ; printf("Meu user id efetivo: %d\n",geteuid()) ; if (setuid(1198) == -1) { perror("Error setuid()") ; exit(-1) ; } printf("Meu user id real : %d\n",getuid()) ; printf("Meu user id efetivo : %d\n",geteuid()) ; exit(0); }
Resultado da execução:
euler:~/> ls -l test_uid -rwxr-xr-x 1 saibel profs 12633 Sep 26 20:47 test_uid* euler:~/> test_uid Meu login e: saibel Meu user id real e: 1198 Meu user id efetivo e: 1198 Error setuid(): Operation not permitted
O primeiro setuid() é interrompido, dado que nenhuma das regras da aplicação foi respeitada. Se por outro lado o programa é lançado a partir do login usertest, não proprietário do arquivo a execução será:
lyapunov:~/> /home/saibel/test_uid Meu login e: usertest Meu user id real e: 1275 Meu user id efetivo e: 1275 Meu user id real : 1275 Meu user id efetivo: 1275 Error setuid(): Operation not permitted
O primeiro setuid() é executado com sucesso: o ID do usuário real 1275 é igual ao valor passado como argumento. Para poder acessar o segundo setuid(), o proprietário do arquivo, saibel, deve posicionar o bit s em 1 para que usertest seja durante o tempo de execução proprietário do arquivo.
euler:~/> chmod u+s test_uid euler:~/> ls -l test_uid -rwsrwxr-x 1 saibel profs 12633 Sep 26 20:47 test_uid* lyapunov:~/> /home/saibel/test_uid Meu login e: usertest Meu user id real e: 1275 Meu user id efetivo e: 1198 Meu user id real : 1275 Meu user id efetivo: 1275 Meu user id real : 1275 Meu user id efetivo: 1198
Antes do lançamento do programa, os IDes real e efetivo são iguais (1275). Em seguida, o ID efetivo torna-se 1198 quando o programa está sendo executado, em razão da presença do bit s. Na chamada de setuid(1275), o ID real é igual ao argumento (2ª regra), ele então gravou o valor 1198 no ID que foi salvo. Na chamada setuid(1198) o ID salvo 1198 é igual ao argumento (3ª regra), o processo encontra seu ID inicial, e portanto suas permissões associadas.
Observação: As mesmas observações da seção 1.4.2 são válidas nesse caso.