2010-10-22 00:29

Trouver une bonne solution au problème du partage des fichiers entre utilisateurs Linux est un cauchemar.

Si elle convient il y a la solution de l’UID unique. Tous les clients accèdent aux fichiers avec le même UID utilisateur. Seulement on ne sais pas qui fait quoi. Et les utilisateurs ne peuvent pas gérer finement leurs droits.

Problème : le umask par défaut est TOUJOURS 0022, ce qui fait que tout fichier créé aura les droits rw– r–– r––. Seul le propriétaire peut écrire et personne d’autre.
Pour partager les fichier, un groupe doit aussi pouvoir écrire.

On peut changer ce umask. Pour la ligne de commande, ça se passe dans les fichiers .bashrc ou .profile, ou dans /etc/profile pour tous les utilisateurs. Pour un partage SFTP, on s’en sort avec un bricolage. Pour le serveur Apache, on s’en sort avec le fichier /etc/apache2/envvars sous Debian.

Si le partage de fichier se fait via un seul service, c’est simple de changer le umask, sinon, c’est compliqué. Et même en changeant tous les umask de tous les services, tout n’est pas parfait : par exemple, Nautilus via SFTP n’en fait qu’à sa tête. Certains clients posent le fichiers et font un chmod derrière : l’enfer. Il y a aussi la puissance des ACL POSIX qui permettent de forcer les droits. Mais là encore, certains clients vous poserons problème.

Enfin, on ne souhaite pas forcément que tous les fichiers soient posés avec l’écriture pour le groupe. On peut souhaiter une meilleure granularité.

D’expérience, j’ai abandonné l’idée du correctif à la source pour me tourner vers un bricolage agissant APRÈS la création du fichier.
La solution la plus simple est bien sûr la tâche cron, qui toutes les X minutes fait un chmod -R g+w sur un dossier. Déjà la solution n’est pas immédiate car désynchronisée de la création de fichiers, et elle rajoute une (très) petite charge supplémentaire à votre système.

Je propose une solution à base d’inotify, qui force les droits dès qu’un fichier est créé :

aptitude install inotify-tools

Et la commande magique :

inotifywait -mrq -e CREATE --format %w%f /tmp/mytest/ | while read FILE; do chmod g=u "$FILE"; done

MAJ 2010-10-30
Pour gérer les espaces en fin de fichiers, et les antislashs :

inotifywait -mrq -e CREATE --format %w%f /tmp/mytest/ | while IFS= read -r FILE; do chmod g=u "$FILE"; done

Merci à vitoreiji (voir commentaires)

La commande inotifywait écoute les événements du dossier /tmp/mytest. Dès qu’un fichier est créé, il est affiché sur la sortie standard. Chaque ligne-fichier est ensuite lue par la boucle while et les droits sont changés. Le g=u donne au groupe les mêmes droits que l’utilisateur (avec g+w, si l’utilisateur pose un fichier rw– ––– –––, les droits deviendraient rw– –w– –––).

Vous pouvez maintenant tester la création/copie de fichiers/dossiers. Même un mkdir -p a/b/c/d/e doit fonctionner.

Pour terminer, on ajoutera tout cela dans un script de démarrage :

vi /usr/local/bin/inotifywait.sh && chmod +x /usr/local/bin/inotifywait.sh
#!/bin/sh
# Take the directory name as argument

inotifywait -mrq -e CREATE --format %w%f "$1" | while read FILE
do
	chmod g=u "$FILE"
done
vi /etc/init.d/inotifywait.sh && chmod +x /etc/init.d/inotifywait.sh
#! /bin/sh

case "$1" in
  start|"")

	rm -f /tmp/inotifywait.log
	/usr/local/bin/inotifywait.sh /path/to/dir/ >/tmp/inotifywait.log 2>&1 &
	
	;;
  restart|reload|force-reload)
	echo "Error: argument '$1' not supported" >&2
	exit 3
	;;
  stop)
	# killall inotifywait ???
	;;
  *)
	echo "Usage: inotifywait.sh [start|stop]" >&2
	exit 3
	;;
esac

:

(sous Debian)

update-rc.d inotifywait.sh defaults

Note : un inconvénient : il y a une limite sur le nombre de fichier surveillés, voir l’option -r dans man inotifywait.

Et enfin la touche finale qui est utile pour que les fichiers créés conservent le groupe du dossier parent : le bit setgid au groupe pour tous les dossiers.

find /path/to/dir -type d -exec chmod g+s {} \;

Liens :

2010-10-22 00:29 · Tags: , , , ,

10 Comments

  1. Hello,

    Est-ce qu’une solution plus classique n’est pas
    - de regrouper les utilisateurs dans un groupe (le plus souvent users);
    - de créer des répertoires partagés appartenant au groupe en question, mais dotés du sticky bit pour le groupe ?

    Soit

    # chown foo:users /home/share
    # chmod g+s /home/share

    bar$ touch /home/share/test
    bar$ ls -l /home/share
    total 0
    -rw-rw-r– 1 bar users 0 23 oct 16:28 test

    ce qui force les fichiers de ce répertoire à adopter l’id du groupe, quel qu’en soit le créateur.

    À la suite de quoi, le contenu de ce répertoire peut être manipulé (effacé, modifié…) par les membres du groupe ?

    Répondre

  2. Bonjour,

    Attention, le sticky bit est tout autre chose (on le met avec le ‘t’ de la commande chmod. Il est utilisé pour le /tmp par exemple).

    Tu veux parler du bit setuid. Je le mentionne à la toute fin de l’article. C’est certes très utile pour conserver le groupe à la création de fichiers.

    Dans ton exemple, le fichier créé récupère les droits d’écriture pour le groupe. Ou bien tu a changé ton umask, ou bien tu as utilisé la technique inotifywait, mais ça n’est pas le bit setuid qui a mis les droits d’écriture au groupe.

    Marc

    Répondre

  3. Pour le sticky bit, effectivement, j’ai confondu les dénominations.

    Pour le reste, au cas où je m’étais emmêlé les pinceaux, je revérifie:

    comme root

    fantasio:~# mkdir /home/share
    fantasio:~# ls -dl /home/share
    drwxr-xr-x 2 root root 4096 oct 24 10:05 /home/share
    fantasio:~# chown root:users /home/share
    fantasio:~# chmod g+s /home/share
    fantasio:~# ls -dl /home/share
    drwxr-sr-x 2 root users 4096 oct 24 10:05 /home/share
    fantasio:~# chmod g+w /home/share
    fantasio:~# ls -dl /home/share
    drwxrwsr-x 2 root users 4096 oct 24 10:05 /home/share

    Comme utilisateur ordinaire membre de users:

    gv@fantasio:/home/share$ umask
    0033
    gv@fantasio:/home/share$ touch foo
    gv@fantasio:/home/share$ ls -l foo
    -rw-r–r– 1 gv users 0 oct 24 10:18 foo
    gv@fantasio:/home/share$ umask 002
    gv@fantasio:/home/share$ touch bar
    gv@fantasio:/home/share$ ls -l
    total 0
    -rw-rw-r– 1 gv users 0 oct 24 10:19 bar
    -rw-r–r– 1 gv users 0 oct 24 10:18 foo

    Comme tu le vois, le masque standard crée des fichiers accessibles seulement en écriture pour le propriétaire, mais une fois modifié, il permet l’écriture aux membres du groupe.

    Dans les mêmes conditions, un autre utilisateur du groupe peut créer un fichier:

    do@fantasio:/home/share$ touch foobar
    do@fantasio:/home/share$ ls -l
    total 0
    -rw-rw-r– 1 gv users 0 oct 24 10:19 bar
    -rw-r–r– 1 gv users 0 oct 24 10:18 foo
    -rw-rw-r– 1 do users 0 oct 24 10:20 foobar

    dans lequel je peux écrire:

    gv@fantasio:/home/share$ ls > foobar
    gv@fantasio:/home/share$ ls -l
    total 4
    -rw-r–r– 1 gv users 0 oct 24 10:18 foo
    -rw-rw-r– 1 do users 22 oct 24 10:21 foobar
    gv@fantasio:/home/share$ rm -f foobar
    gv@fantasio:/home/share$ exit

    Ça me paraît donc une stratégie suffisante quoique limitée pour travailler à plusieurs sur des fichiers. Mais je reconnais que n’ayant jamais géré que des machines uni-personnelles, je n’ai jamais été confronté à une mise en pratique, donc…

    Cordialement

    Répondre

  4. D’accord d’accord, ta démonstration montre comment partager des fichiers, mais en modifiant le umask.

    Dans ce que tu montres, l’utilisateur ‘do’ a bien un umask de 002, qui n’est pas l’umask par défaut 022 présent sur la majorité des distribution Linux.

    Bien sûr qu’en changeant le umask on peut partager les fichiers.

    Mais mon article explique justement comment le faire SANS modifier le umask. Car modifier le umask pose certains problèmes.

    Répondre

  5. Loin de moi l’idée de polémiquer ;)

    Je crois quand même me souvenir qu’il y a une bonne dizaine d’année, les distribs étaient configurées pour que tout nouvel utilisateur appartienne au groupe users. Je me demande si ça n’est pas la Redhat ou Mandrake qui a introduit les groupes uni-personnels qui permettaient précisément d’avoir comme umask 0022 tout en préservant la confidentialité des fichiers personnels (puisque le groupe autorisant l’accès en écriture était restreint à ce même utilisateur).

    Si tu avais des références sur les problèmes caussés par les changements d’umask, ça m’intéresserait.

    Cordialement,

    Répondre

  6. Salut,

    Sujet très intéressant que inotify!
    Sais-tu qu’il existe un programme nommé incron qui utilise inotify et facilite ce que tu fais ?

    Répondre

  7. En fait je l’ai testé mais je n’ai pas réussi à le faire fonctionner.
    Tu l’as testé toi ?

    Répondre

  8. Oui en effet, je l’ai testé et je l’utilise.
    J’ai utilisé ce tuto http://dmesg.fr/categorie-logiciels/75-incron-executer-des-actions-selon-des-evenements-du-systeme-de-fichiers que je conseille car il est assez bien fait.

    Je n’ai par contre pas utilisé incron pour faire la même chose que dans le tuto : en fait, quand un fichier multimedia est téléchargé (et donc créé), je change le groupe en “media” et je donne comme toi le droit en écriture au groupe.

    Pour résumer, tu installes incron :
    aptitude install incron

    Soit tu édites les tables dans /etc/incron.d/ manuellement (à toi de les créer lors de la première utilisation, tu peux mettre les noms que tu veux). Ces tables seront les table “system”.
    Soit tu utilises “incrontab -e” pour éditer une table qui se trouve dans /var/… (je ne sais plus) et qui porte le nom de l’utilisateur qui a lancé la commande. Ces tables seront les tables “user”. root peut créer une table de cette façon aussi.

    Pour les différentes actions, regarde dans le tuto ce sera mieux expliqué :)

    Répondre

  9. « le bit setuid au groupe pour tous les dossiers.
    find /path/to/dir -type d -exec chmod g+s {} \; » :

    La commande indiquée fixe le bit SGID, et non pas le bit SUID ;)

    Répondre

  10. Merci ! j’ai corrigé la coquille.

    Répondre

Leave a Reply to hatul Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>