Pour résoudre cette problématique, mon interface génère un fichier qui contient une ligne par utilisateur, chaque ligne étant constituée du login, du password et d'un flag indiquant si le compte est autorisé à se connecter en SSH. Le séparateur est le caractère espace.

Le fichier (/usr/share/accounts.lst) ressemble donc à:

user1 password1 0
user2 password2 1
user3 password3 1
user4 password4 0
user5 password5 0
user6 password6 0

Attention: le caractère de fin de ligne doit être Line Feed (chr(10) en php).

Le script commence par une initialisation des variables utiles:

  • FILE_BASE est le répertoire où est enregistré le fichier des utilisateurs,
  • HOME_BASE est le répertoire où seront créés les "homes" des utilisateurs,
  • GROUP est le groupe unix qui sera attribué à l'utilisateur.
#!/bin/bash
 
FILE_BASE="/usr/share"
HOME_BASE="/home/"
GROUP="uploader"

Ensuite, le fichier est lu. Pour cela, nous faisons un read qui permet de lire l'entrée en console, et nous lui transmettons un cat du fichier. Nous affectons les données à 3 variables: USER, PASSWORD et SSH. C'est l'équivalent d'un split() sur le caractère espace.

cat "$FILE_BASE/accounts.lst" | \
while read USER PASSWORD SSH
do

Ensuite, soit l'utilisateur est autorisé à se connecter en SSH et nous lui affectons un interpréteur de commande (/bin/sh), soit il n'est pas autorisé et nous le forçons sur /bin/false qui interdit l'accès à la console:

# Checks if user needs SSH access or not
   if [ $SSH == 1 ]; then
      SHELL="-s /bin/sh"
   else
      SHELL="-s /bin/false"
   fi

Ensuite, nous allons regarder si l'utilisateur existe déjà, en comptant le nombre de lignes dans le catalogue passwd qui concernent l'utilisateur à traiter. Le résultat est soit 0 (aucune ligne ne concerne cet utilisateur) soit 1. Si l'utilisateur existe, nous ferons simplement un usermod sur le compte utilisateur pour lui attribuer le bon shell, sinon nous le créons avec un useradd.

Dans les deux cas, nous forçons son mot de passe en appelant chpasswd en lui passant le doublet user - password.

if [ `getent passwd $USER | wc -l` == 1 ]; then
# User exists, just modifying
      `usermod $SHELL $USER > /dev/null 2>&1`
      `echo "$USER:$PASSWORD" | chpasswd`
   else
# New user, to create
      `useradd -g $GROUP -m -d $HOME_BASE$USER $SHELL $USER`
      `echo "$USER:$PASSWORD" | chpasswd`
   fi
done

Il ne reste ensuite plus qu'à effacer le fichier.

Le script final donne donc:

#!/bin/bash
 
FILE_BASE="/usr/share"
HOME_BASE="/home/"
GROUP="uploader"
 
cat "$FILE_BASE/accounts.lst" | \
while read USER PASSWORD SSH
do
   if [ $SSH == 1 ]; then
      SHELL="-s /bin/sh"
   else
      SHELL="-s /bin/false"
   fi
 
   if [ `getent passwd $USER | wc -l` == 1 ]; then
# User exists, just modifying
      `usermod $SHELL $USER > /dev/null 2>&1`
      `echo "$USER:$PASSWORD" | chpasswd`
   else
# New user, to create
      `useradd -g $GROUP -m -d $HOME_BASE$USER $SHELL $USER`
      `echo "$USER:$PASSWORD" | chpasswd`
   fi
 
done
 
`rm -f $FILE_BASE/accounts.lst`