J'ai un processus qui est démarré par un damon exécuté en tant que root, maintenant je veux "rétrograder" les privilèges de ce processus à ceux de votre utilisateur moyen. Est-ce possible? Si oui comment?
PS: exécuter unix sur un mac
J'ai un processus qui est démarré par un damon exécuté en tant que root, maintenant je veux "rétrograder" les privilèges de ce processus à ceux de votre utilisateur moyen. Est-ce possible? Si oui comment?
PS: exécuter unix sur un mac
Réponses:
Le processus lui-même doit appeler setuid (2). Vous devriez également étudier son exécution dans chroot (8) si vous ne l'êtes pas déjà. Pour autant que je sache, root n'a aucun moyen de changer l'uid d'un autre processus.
Si la raison pour laquelle vous l'exécutez en tant que root est de lier des ports, je suggère de l'exécuter en tant qu'utilisateur normal sur un port supérieur et d'utiliser ipfw (8) sur OS X pour transférer le port 80/443 / etc vers le port supérieur:
http://support.crashplanpro.com/doku.php/recipe/forward_port_443_to_pro_server_on_mac_osx
setuid()
seul ne suffit absolument pas.
sudo tcpdump -Z
utilise initgroups (3), setgid (2) et setuid (2) pour supprimer les privilèges root de son propre processus.
# 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
(Enfin!) Est précisément le paradigme droit sur unix, et doit toujours être suivi. De plus, une fonction "droproot" responsable vérifie que son uid et son gid ont bien été définis, même si les trois fonctions principales ont réussi.
Vous pouvez exécuter des commandes en tant que d'autres utilisateurs en utilisant su
:
su USERNAME -c COMMAND
S'exécutera COMMAND
avec les privilèges accordés à USER
.
Notez que, par défaut, su
utilisera l'interpréteur de commandes de l'utilisateur cible pour exécuter la commande. En revanche, le comportement par défaut de sudo
est de traiter le COMMAND
comme un programme autonome, c'est-à-dire exécuté l'environnement actuel. Bien sûr, ces comportements par défaut peuvent être modifiés avec divers commutateurs et variables d'environnement.
su
cela ne fonctionne pas si USERNAME n'a pas de shell défini (ou /bin/false
) alors que sudo fonctionne.
su
le reflétera. Cependant, on peut toujours remplacer cela en utilisant le -s
commutateur. Notez que le but de su
est d'imiter le comportement d'un utilisateur donné - qui est normalement influencé par son shell. En revanche, sudo
ignorerait (par défaut) le paramètre de shell de l'utilisateur cible.
Pour supprimer des privilèges, vous avez besoin d'un utilisateur non root pour accéder à. Ensuite, il suffit de passer à cet utilisateur:
#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);
Notez que cela se fait dans le programme lui-même, plutôt que dans un script wrapper. De nombreux programmes nécessitent des privilèges root dans un but spécifique (par exemple pour se lier à un port de faible nombre), mais n'ont pas besoin de root après cela. Ces programmes démarrent donc en tant que root, mais abandonnent ensuite les privilèges une fois qu'ils ne sont plus nécessaires.
Si vous n'avez pas du tout besoin des privilèges root, alors ne l'exécutez pas en tant que root. Par exemple:
# 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
fonction définit uniquement l' UID effectif , pas le véritable UID. Vous devez utiliser setreuid
si vous ne voulez pas que le processus puisse récupérer les privilèges. (Et le code ci-dessus ne traite pas non plus des privilèges de groupe supplémentaires. Il ne convient que pour lancer du code principalement fiable.)
setuid()
définit des ID utilisateur réels et enregistrés; vous pensez peut-être seteuid()
. Tous les systèmes ne l'ont pas setreuid()
, il ne peut donc pas être utilisé un peu partout. La sémantique exacte de setuid()
est compliquée, mais si vous avez euid 0, vous serez en mesure de supprimer tous les privilèges d'ID utilisateur traditionnels avec setuid()
. La plus grande omission dans cette réponse est que initgroups
ou setgroups
doit être appelé ainsi que setgid
et setuid
, et que des affirmations plus approfondies doivent être faites à la fin.
Si vous exécutez un exécutable différent, c'est-à-dire que vous appelez execve
ou une autre famille de exec
fonctions, peut-être indirectement via une fonction comme system
ou popen
, et que le processus enfant doit s'exécuter sans privilèges dès le début, alors le plus simple est d'obtenir un shell impliqué, et appeler su
. Voici un aperçu de l'apparence du code en Perl, montrant la citation nécessaire pour:
$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;
Si le processus enfant doit démarrer en tant que root mais supprimer les privilèges plus tard, consultez le code dans cette réponse , qui illustre comment rétrograder les privilèges dans un processus.