Page suivante Page précédente Table des matières

7. Les applications X avec un identificateur d'utilisateur (User-id) différent

Supposez que vous vouliez faire tourner un outil graphique de configuration qui nécessite d'avoir les privilèges du compte root alors que la session X actuelle se déroule sous votre compte. Cela peut sembler étrange au premier abord, mais le serveur X ne permettra pas à cet outil d'accéder à votre unité d'affichage. Comment cela est-il possible alors que root peut normalement tout faire ? Et comment contourner ce problème ?

Élargissons le propos au cas où l'on veut faire tourner une application X, sous un identificateur d'utilisateur clientuser, alors que la session X a été lancée par serveruser. Si vous avez lu le paragraphe sur les cookies, il est évident que clientuser ne peut pas accéder à votre unité d'affichage : ~clientuser/.Xauthority ne contient pas le cookie magique qui permet d'accéder à l'unité d'affichage. Le cookie correct se trouve dans ~serveruser/.Xauthority.

7.1 Plusieurs utilisateurs sur le même hôte

Naturellement, tout ce qui marche pour un X distant marchera aussi pour un X à partir d'un identificateur d'utilisateur différent (particulièrement slogin localhost -l clientuser). Et ici l'hôte client et l'hôte serveur sont précisément les mêmes. Cependant, quand les deux hôtes sont les mêmes, il y a quelques raccourcis pour transférer le cookie magique.

On supposera que l'on utilise su pour passer d'un identificateur utilisateur à l'autre. Essentiellement, il faut écrire un script qui appelle su, mais enveloppe la commande que su exécute d'un peu de code qui effectue les tâches nécessaires pour le X distant. Ces tâches nécessaires sont l'initialisation de la variable DISPLAY et le transfert du cookie magique.

L'initialisation de DISPLAY est relativement facile ; il faut simplement définir DISPLAY="$DISPLAY" avant d'exécuter l'argument de la commande su. Donc, il faut simplement faire :

su - clientuser -c "env DISPLAY="$DISPLAY" clientprogram &"

Ce n'est pas tout, il faut encore transférer le cookie. On peut le retrouver en utilisant xauth list "$DISPLAY". Cette commande renvoie le cookie dans un format qui convient pour l'utiliser dans la commande xauth add : ce dont nous avons justement besoin !

On pourrait imaginer passer le cookie par l'intermédiaire d'un canal de transmission. Manque de chance, ce n'est pas si facile de passer quelque chose à la commande su par l'intermédiaire d'un canal de transmission car su attend le mot de passe de l'entrée standard. Cependant, dans un script shell on peut jongler avec quelques descripteurs de fichiers et arriver à le faire.

Donc, on écrit un script de ce style en le paramétrant avec clientuser et clientprogram. Pendant que nous y sommes, améliorons un peu ce script, ça va le rendre un peu moins compréhensible mais un peu plus robuste. Le tout ressemble à cela :

#!/bin/sh

if [ $# -lt 2 ]
then echo "usage: `basename $0` clientuser command" >&2
     exit 2
fi

CLIENTUSER="$1"
shift

# FD 4 becomes stdin too
exec 4>&0

xauth list "$DISPLAY" | sed -e 's/^/add /' | {

    # FD 3 becomes xauth output
    # FD 0 becomes stdin again
    # FD 4 is closed
    exec 3>&0 0>&4 4>&-

    exec su - "$CLIENTUSER" -c \
         "xauth -q <&3
          exec env DISPLAY='$DISPLAY' "'"$SHELL"'" -c '$*' 3>&-"

}

Je pense que c'est portable et que cela fonctionne suffisamment correctement dans la plupart des circonstances. Le seul défaut auquel je pense en ce moment est dû à l'utilisation de '$*', les guillemets simples dans command vont perturber les guillemets de l'argument('$*') de la commande su. Si cela entraîne quelque chose de vraiment gênant, envoyez-moi un courrier électronique.

Nommez le script /usr/local/bin/xsu, et vous pouvez faire :

xsu clientuser 'command &'

Cela ne peut pas être plus facile, à moins que vous ne vous débarrassiez du mot de passe. Oui, il existe des moyens pour y arriver (sudo), mais ce n'est pas l'endroit pour en parler.

Le petit script xsu mentionné ci-dessus a servi comme base pour un script plus étendu appelé sux qui a, apparemment, trouvé sa place comme paquet dans la distribution Debian.

7.2 Root est l'utilisateur client

Évidemment, tout ce qui marche pour un client non root doit fonctionner pour root. Cependant, avec root vous pouvez faire cela encore plus facilement, car celui-ci peut lire le fichier ~/.Xauthority de tout le monde. Il n'y a pas besoin de transférer le cookie. Tout ce qu'il y a à faire consiste à initialiser DISPLAY, et à faire pointer XAUTHORITY sur ~serveruser/.Xauthority. Donc, vous pouvez écrire :

su - -c "exec env DISPLAY='$DISPLAY' \
                  XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
                  command"

Et, en mettant cela dans un script, cela donne quelque chose comme 

#!/bin/sh
if [ $# -lt 1 ]
then echo "usage: `basename $0` command" >&2
     exit 2
fi
su - -c "exec env DISPLAY='$DISPLAY' \
                  XAUTHORITY='${XAUTHORITY-$HOME/.Xauthority}' \
                  "'"$SHELL"'" -c '$*'"

Nommez le script /usr/local/bin/xroot, et vous pouvez faire :

xroot 'control-panel &'

Cependant, si vous avez déjà initialisé xsu , il n'y a pas de vraie raison de faire cela.


Page suivante Page précédente Table des matières