Comment définir SGID en PHP?
Je n'arrive pas à définir le bit SGID depuis PHP.
J'ai ce répertoire:
4 drwxrwsr-x 12 www-data mygroup 4096 Oct 7 16:05 mydir
Notez le bit SGID. Donc, si je crée simplement un répertoire à partir du shell avec mkdir test, j'obtiens
4 drwxr-sr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Notez que le bit SGID est hérité. Mais je voudrais le groupe inscriptible (ce que mon umask 22ne permet pas) donc je peux simplement chmod 02775 testet je suis parfaitement content:
4 drwxrwsr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Maintenant, j'aimerais faire la même chose à partir d'un script PHP. Naturellement, je m'attendrais à ce que cela fonctionne:
mkdir("/mydir/test2");
chmod("/mydir/test2", 02775);
Mais ce n'est pas le cas et j'obtiens ceci à la place (le SGID est réinitialisé):
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 16:30 test2
Voici quelques autres expériences utiles:
mkdir("/mydir/test3");
mkdir("/mydir/test4");
passthru("chmod 02775 '/mydir/test4'");
mkdir("/mydir/test5");
passthru("chmod g+w '/mydir/test5'");
Les résultats sont
4 drwxr-sr-x 2 www-data mygroup 4096 Oct 7 16:39 test3
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 16:39 test4
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 17:06 test5
Fait intéressant, mkdir()seul a conservé le SGID, mais le chmod()réinitialise, même à travers passthru().
Je sais que le manuel PHP dit chmodque la commande n'attend que trois chiffres octaux, mais j'ai lu aussi cette question de stackoverflow et il semble que le manuel contient des informations obsolètes et que d'autres peuvent affecter le SGID. De plus, cela ne devrait pas affecter les passthru()versions, n'est-ce pas? La même question stackoverflow mentionne quelque chose à propos du chmod()besoin d'être "le dernier à être appelé" après chown()et chgrp(), mais je n'utilise aucun de ceux-ci.
Qu'est-ce que je fais mal?
Réponses
Est-ce que cela fonctionne sur un serveur Web ou simplement en tant que script CLI? Si CLI, utilisateur ou root?
Aussi, pourquoi des répertoires? SGID est utilisé sur les fichiers programme, pour permettre à un utilisateur d'exécuter un programme / script en tant qu'autre utilisateur, comme "sudo". Avez-vous essayé de tester cela sur des fichiers plutôt que sur des répertoires?
En fin de compte, le seul moyen que j'ai pu trouver pour obtenir les autorisations dont j'ai besoin est de profiter du comportement correct de mkdir()et d'éviter d'appeler, chmod()ce qui semble réinitialiser le bit SGID quoi qu'il arrive. La seule façon dont je peux penser à faire cela est de changer le umask avec umask():
$myumask = umask(2); mkdir("/mydir/test6"); umask($myumask);
Cela semble fonctionner correctement:
4 drwxrwsr-x 2 www-data mygroup 4096 Oct 9 14:22 test6
Cela me laisse avec la question soulevée dans la note de https://www.php.net/manual/en/function.umask.php: que tous les threads d'un serveur Web multithread partagent le même umask , ce qui conduit évidemment à un comportement indésirable et imprévisible. Heureusement, dans mon cas, j'ai pu m'assurer que toutes les créations de répertoires sont effectuées dans un contexte monothread (essentiellement, lors du premier test d'un script) et donc je me sens en sécurité. Par conséquent, c'est une solution de contournement utile mais pas une solution générale.