(Courriels de diversion: <cahots@deroutant-coudrait.com> <antipathiques@denaturait-connectera.com> <parcellarise@bafouilliez-detecterait.com> <vexes@martelait-irrespirable.com> <empêtreraient@vilipendait-desoeuvre.com> <satisfaisaient@melangerai-lecheront.com> <replats@deplafonnent-debraguetter.com> <soulignera@emblavure-edictees.com> <apprehendais@sortis-reeduquerions.com> <galvaude@puisse-annonciateur.com> )


Pourquoi ce script ne marche que partiellement sous mandrake 9beta1 et3 ?
Encodage des comptes unix ok mais pas samba !



#!/usr/bin/env python

# ========= accounts.py ===========================================
# Création automatique de comptes utilisateurs Unix & Samba sur un
# serveur Linux destiné à la gestion d'un intranet scolaire
# Ce script a été testé seulement sous Linux SuSE 6.3 -> 7.2
#
# Explications : voir http://www.ulg.ac.be/cifen/inforef/swi
# =================================================================

import string                      # fonctions de traitement des chaînes
import os                          # appels au système d'exploitation
import sys                         # fonctions système généralistes
from crypt import crypt            # routines de cryptage
from whrandom import randint       # générateur de nombres aléatoires
from os.path import exists         # test d'existence d'un fichier
import pwd                         # accès aux infos de /etc/passwd
import grp                         # accès aux infos de /etc/group

version = '20/01/2002'
profGrp = "staff"
lettres = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
lettresAcc = lettres + "éèçàùêëâî-" + string.digits

def deleteLine(keyword,fichier):
    # du fichier spécifié, supprimer les lignes qui commencent par
    # la chaîne <keyword> suivie d'un ":"
    if len(keyword) == 0:
        return
    # 1) renommer le fichier source, puis l'ouvrir en lecture :
    os.rename(fichier,'source')
    fis = open('source', 'r')
    # 2) créer un nouveau fichier et l'ouvrir en écriture :
    fid = open(fichier, 'w')
    # 3) transférer de l'un à l'autre, en filtrant :
    while 1:
        li = fis.readline()            # lire les lignes une par une
        if len(li) == 0:               # détecter la fin de fichier
            break
        ll = string.split(li,':')      # séparer les sous-chaînes
        if ll[0] == keyword:           # sauter les lignes qui commencent
            pass                       # par une sous-chaîne identique à
keyword
        else:
            fid.write(li)              # transcrire les autres
    fis.close()
    fid.close()
    os.system('chmod 600 '+ fichier)   # attributs de sécurité
    os.remove('source')                # effacer l'ancienne version


def sambaPass(user,passwd):
    # Pour inscrire le mot de passe dans la base de sécurité de Samba, on
doit
    # utiliser la commande <smbpasswd -s> , laquelle attend 2 entrées
clavier.
    # (le mot de passe, 2 fois pour confirmation)
    # La solution pour passer ces entrées est d'ouvrir un 'pipe' à l'aide de
    # la fonction os.popen("commande"). Cette fonction retourne un
    # "objet fichier" relié au pipe, auquel on peut appliquer les méthodes
    # applicables aux fichiers, telle write() :
    os.popen('smbpasswd -s -a -e ' + user, 'w').write(passwd +'\n' +passwd
+'\n')


def deleteDirectory(dir):
    # Effacement du répertoire dir (après confirmation si non vide) :
    if exists(dir):
        try:
            os.rmdir(dir)
        except:
            print "*********************** !! ATTENTION !!
************************"
            print "Le répertoire %s contient encore les éléments suivants :"
% (dir)
            print os.listdir(dir)
            dd = raw_input("Etes-vous certain de vouloir l'effacer (o/n) ?
")
            if string.lower(dd[0]) == 'o':
                os.system('rm -R ' + dir)               # -R pour
récursivité
    else:
        print "Le répertoire %s n'existe pas !" % (dir)


def savepasswords():
    # Sauvegarde des fichiers de mots de passe préexistants (Unix & Samba)
    pwFiles =["/etc/private/smbpasswd","/etc/passwd"]
    for pFile in pwFiles:
        n =0
        while 1:
            if not exists(pFile + "Bak" + str(n)):
               bkFile = pFile + "Bak" + str(n)
               break
            else:
               n = n+1
        os.system("cp " + pFile + " " + bkFile)
        print "Note : le fichier %s précédent est" % (pFile)
        print "sauvegardé sous le nom %s." % (bkFile)


def existsUser(u):
   # Vérifier si l'utilisateur u est bien répertorié dans /etc/passwd
   try:
      t = pwd.getpwnam(u)     # retourne un tuple avec paramètres user
   except:
      return 0
   else:
      return 1


def existsGroup(g):
   # Vérifier si le groupe g est bien répertorié dans /etc/group
   try:
      t = grp.getgrnam(g)     # retourne un tuple avec paramètres du groupe
   except:
      return 0
   else:
      return 1


def notUnixWord(mot):
    # <mot> est-il un label UNIX correct ? retourne 1 si non
    if len(mot) <1 or len(mot) >8:
       return 1
    # le premier caractère doit être alphabétique :
    if mot[0] not in lettres:
       return 1
    # les autres caractères doivent être alphanumériques :
    for c in mot:
       if not (c in lettres or c in string.digits):
          return 1
    return 0


def createGroup(group):
    # Création du groupe Unix + création des répertoires associés
    global profGrp, boss, quotas
    if existsGroup(group):
       print "Le groupe-classe %s existe déjà." % (group)
    else:
       print "*** Création du groupe-classe %s : ***" % (group)
       os.system('groupadd '+ group)

    try:
       os.mkdir('/home/' + group, 0755)
       os.mkdir('/home/' + group + '/bureau', 0755)
       os.mkdir('/home/' + group + '/apps', 0755)
       os.mkdir('/home/' + group + '/start', 0755)
       os.mkdir('/home/' + group + '/smenu', 0755)
    except OSError,Errno:             # <File exists> error
       if Errno[0] == 17:
          print"Le répertoire home existe déjà pour le groupe %s." % (group)
       else:
          print "Erreur système N°", Errno

    try:
       os.mkdir('/home/siteweb/' + group, 0755)
    except OSError,Errno:             # <File exists> error
       if Errno[0] == 17:
          print"Le rép. home/siteweb existe déjà pour le groupe %s." %
(group)
       else:
          print "Erreur système N°", Errno

    # Le propriétaire des répertoires créés est un membre du groupe.
    # Par défaut, son nom est celui du groupe (converti en minuscules):
    boss = string.lower(group)
    if not existsUser(boss):
        print "Il est créé automatiquement un utilisateur propriétaire"
        print "pour l'environnement de travail de cette classe."
        print 'Son nom est : "%s".' % (boss)
        bossPass = 'abcde'              # mot de passe
        b = raw_input("Mot de passe du propriétaire [abcde] : ")
        if len(b) >0:
            bossPass = b
        # Pour comprendre ce qui suit, veuillez consulter la documentation
        # concernant le cryptage des mots de passe UNIX :
        salt = chr(randint(1,26)+64) + chr(randint(1,26)+96)
        crPass = crypt(bossPass,salt)
        # Répertoire personnel du Boss = rép. réservé au groupe :
        os.system("useradd -g %s -p %s -d /home/%s -c propriétaire %s"
                   % (group, crPass, group, boss))
        # Enreg. du mot de passe également crypté à la mode Samba
        # (l'utilisateur concerné doit exister au préalable !) :
        sambaPass(boss, bossPass)

    # Appropriations (paramètre -R pour inclure les sous-répertoires):
    if exists("/home/" + group):
       os.system("chgrp -R %s /home/%s" % (group, group))
       os.system("chown -R %s /home/%s" % (boss, group))
    else:
       print "??? Répertoire /home/%s inexistant ???" % (group)
       sys.exit()
    if exists("/home/siteweb/" + group):
       os.system("chgrp -R %s /home/siteweb/%s" % (group, group))
       os.system("chown -R %s /home/siteweb/%s" % (boss, group))
    else:
       print "??? Répertoire /home/siteweb/%s inexistant ???" % (group)
       sys.exit()

    # Un groupe de profs aura tous les droits sur les répertoires
    # "privés" des élèves :
    print "Un groupe de professeurs aura droit de regard sur les"
    print "répertoires personnels des élèves de cette classe."
    print "Quel nom choisissez-vous pour ce groupe de profs ?"
    print "(Le groupe sera créé s'il n'existe pas déjà) [%s] : " %
(profGrp),
    b = raw_input()
    if len(b) >0:
        profGrp = b
    os.system('groupadd '+ profGrp)


def setQuotas(group):
    # Attribution de quotas au "chef" de groupe :
    global quotas
    if quotas =='o':
       while 1:
          proto = raw_input("""Veuillez entrer le nom de l'utilisateur
choisi comme
prototype pour l'établissement des quotas disque
attribués à ces élèves : """)
          if existsUser(proto):
             # attribution de ces quotas au "chef" du groupe :
             os.system("edquota -p %s -u %s" % (proto, string.lower(group)))
             break
          else:
             print "******* Cet utilisateur n'existe pas !!!"


def scanUsers(step):
    # traitement des données utilisateur pour créer les comptes :
    global linUsers
    fichier = open(usersFile,'r')
    count = 0
    while 1:
        ligne = fichier.readline()
        if not ligne:                           # détection de la fin de
fichier
            break                               # (la ligne lue est vide)
        # nom de l'utilisateur, groupe, mot de passe, commentaire :
        count = count +1
        ll = string.split(ligne)
        if len(ll) <3:                          # ligne incomplète (moins de
3 champs)
            print "*** Ligne %s incomplète dans le fichier source. ***" %
(count)
            continue

        if len(ll[0]) <9 and len(ll[1]) <9 and len(ll[2]) <9:
            # analyse de la ligne suivant nouvelle convention :
            user = ll[0]
            group = ll[1]
            passw = ll[2]
            comment = string.join(ll[3:])
        else:
            # analyse de la ligne suivant ancienne convention :
            user = string.strip(ligne[:8])
            group = string.strip(ligne[8:16])    # élimination des espaces
            passw = string.strip(ligne[16:24])   # en début et fin de chaîne
            comment = string.strip(ligne[24:])

        # Vérifications diverses. D'abord s'assurer que les identifiants
sont OK :
        if notUnixWord(user) or notUnixWord(group):
            print
            print "User = %s , Group = %s, Passwd = %s ???" %
(user,group,passw)
            print "*** Ligne %s incorrecte dans le fichier source. Job
annulé. ***" % (count)
            sys.exit()

        # Il faut s'assurer que le commentaire associé à chaque utilisateur
ne
        # contienne que des caractères "autorisés" (sinon -> erreur
système).
        if len(comment) ==0:
            comment ='---'
        else:
            # Construire d'abord la liste des caractères "illégaux" présents
:
            lc =[]
            for cx in comment:
                if cx not in lettresAcc:
                    lc.append(cx)
            # remplacer les caractères "illégaux" trouvés par des '_' :
            for cx in lc:
                comment = string.replace(comment,cx,'_')

        # Mise à jour de la liste des groupes déjà rencontrés :
        if not(group in grpList):
            grpList.append(group)       # on ajoute le groupe à la liste
            if step == 1:
               # Création du groupe et de ses répertoires associés :
               print ""
               createGroup(group)
               setQuotas(group)

        if step == 2:
            # Création des utilisateurs et de leurs répertoires personnels
            # le rép. <home> attribué à chaque élève est celui du groupe :
            homeDir = '/home/%s/%s' % (group, user)
            if existsUser(user):
               print "L'utilisateur %s existe déjà." % (user)
            else:
               # Voir documentation sur le cryptage des mots de passe :
               salt = chr(randint(1,26)+64) + chr(randint(1,26)+96)
               crPass = crypt(passw,salt)
               # Ajout d'un compte utilisateur :
               os.system("useradd -g %s -p %s -d %s -c %s %s"
                          % (group, crPass, homeDir, comment, user))
               # encodage des mots de passe également à la sauce Samba :
               sambaPass(user, passw)

            # Création d'un sous-répertoire personnel privé pour chacun :
            if not exists(homeDir):
               os.mkdir(homeDir)

            # copie d'un "squelette" d'environnement Linux s'il y a lieu:
            if linUsers =='o':
               os.system("cp -au /etc/skel/.[^.]* %s" % (homeDir))
            # Note : la syntaxe utilisée ici fait appel à l'expression
            # régulière [^.] pour désigner "tout autre caractère que le
point"
            # (on copie ainsi tout ce qui commence par un point et un seul,
            #  en évitant de copier aussi le répertoire parent)

            # (Ré)Appropriations :
            os.system("chgrp -R %s /home/%s/%s" % (profGrp, group, user))
            os.system("chown -R %s /home/%s/%s" % (user, group, user))
            os.system("chmod 2770 /home/%s/%s" % (group, user))
            # Droits d'accès : le 2 en premier lieu positionne le bit GID,
            # De ce fait les fichiers mémorisés dans ce répertoire seront
            # attribués au même groupe que le répertoire lui-même (càd
profGrp)

            # (Re)Création des liens symboliques pour la configuration du
bureau Windows :
            for item in ["apps","bureau","smenu","start","background"]:
               os.system("ln -sfn /home/%s/%s %s/%s" % (group, item,
homeDir, item))

            # Répertoire personnel accessible aux autres en lecture :
            if not exists("/home/siteweb/%s/%s" % (group, user)):
               os.mkdir("/home/siteweb/%s/%s" % (group, user))

            # (Ré)Appropriations :
            os.system("chgrp -R %s /home/siteweb/%s/%s" % (profGrp, group,
user))
            os.system("chown -R %s /home/siteweb/%s/%s" % (user, group,
user))
            os.system("chmod 2775 /home/siteweb/%s/%s" % (group, user))

        elif step == 4:
            # établissement des quotas (semblables à ceux du "chef"
            # de groupe, lequel a reçu ceux du prototype) :
            print "Etablissement des quotas disque pour %s" % (user)
            proto = string.lower(group)
            os.system("edquota -p %s -u %s" % (proto, user))

        elif step == 5:
            # Suppression des utilisateurs :
            if existsUser(user):
               os.system("smbpasswd -d %s" % (user))
               # la ligne ci-dessus ne fait que désactiver les comptes Samba
               # la fonction ci-dessous efface les lignes correspondantes :
               if exists('/etc/private/smbpasswd'):
                   deleteLine(user, '/etc/private/smbpasswd')
               os.system('userdel ' + user)
               # Suppression des répertoires de l'utilisateur :
               os.system("rm -R /home/%s/%s" % (group, user))   # -R pour
récursivité
               os.system("rm -R /home/siteweb/%s/%s" % (group, user))
            else:
               print "L'utilisateur %s n'existe pas !!!" % (user)

    fichier.close()


###### Main program #######################

print '''
===========================================================
       Création automatique de comptes utilisateurs.
    (C) G.Swinnen - Version du %s - Licence GPL
===========================================================

Il faut avoir préparé à l'avance un fichier texte contenant
une ligne pour chaque élève, avec les champs suivants
séparés par des espaces : Identifiant de l'élève (max 8c)
Classe(max 8c) Mot de passe(max 8c) Commentaire(max 40c).
Ce fichier peut être créé aisément à partir de la base de
données PROSEC de l'école, au moyen du logiciel NETUSERS
de G.Swinnen (logiciel à utiliser sous Window$).

Pour que les mots de passe soient transcrits aussi dans la
base de sécurité de Samba (fichier /etc/private/smbpasswd),
il faut que le serveur Samba soit actif, et notamment que
/etc/smb.conf contienne l'indication correcte du chemin
menant à ce fichier (lequel doit être bien protégé).

(Détails sur http://www.ulg.ac.be/cifen/inforef/swi)

                   ... / ...''' % (version)
k = raw_input()
print '''Si vous le souhaitez, des quotas disque pourront être
automatiquement établis pour chaque élève, mais pour cela
il faut que le système de quotas soit activé, et il faut
avoir défini à l'avance les quotas d'un ou de plusieurs
utilisateurs qui serviront de "prototypes".
(Vous pouvez établir ou modifier ces quotas à tout moment :
 Il vous suffira pour cela de relancer le présent script).

Afin que les répertoires personnels des élèves soient
accessibles à certains professeurs, il faut que les noms
de ceux-ci soient incorporés dans un ou plusieurs groupe(s)
spécialement créé(s) à cet effet. Vous pouvez créer un groupe
différent pour chaque classe si nécessaire.
(Un même professeur peut faire partie de plusieurs groupes).
'''

usersFile = raw_input("Veuillez entrer le nom du fichier décrivant les
élèves : ")
if not exists(usersFile):
   print 'Ce fichier est introuvable ! Recommencez.'
   sys.exit()

choix = raw_input('''
Veuillez à présent entrer :
'c' pour créer les comptes utilisateur pour ces élèves,
    ou bien pour établir/modifier leurs quotas disque
's' pour supprimer les comptes de ces élèves
'q' pour quitter le présent script sans rien faire : ''')

grpList =[]
scanUsers(0)        # test du fichier source
grpList =[]

if choix =='c':
    while 1:
       quotas = raw_input("""
Désirez-vous établir ou modifier des quotas d'espace disque
pour ces élèves (o/n) ? : """)
       quotas = string.lower(quotas[0])
       if quotas =='o' or quotas =='n':
           break
    while 1:
       linUsers = raw_input("""
Désirez-vous installer un environnement Linux pour chaque utilisateur ?
 (Répondez NON à cette question si vos postes de travail fonctionnent
  sous Window$ exclusivement)     (o/n) ? : """)
       linUsers = string.lower(linUsers[0])
       if linUsers =='o' or linUsers =='n':
           print
           break
    # Création du répertoire réservé aux pages Web perso. des élèves :
    if not exists('/home/siteweb'):
        os.mkdir('/home/siteweb',0755)
    # Création de la base de sécurité de Samba si elle n'existe pas déjà :
    if not exists('/etc/private/smbpasswd'):
        print "Base de données smbpasswd inexistante - Essai de création :"
        if not exists('/etc/private'):
            os.mkdir('/etc/private', 0500)
        while 1:
            tt = os.system('cat /etc/passwd | mksmbpasswd.sh >
/etc/private/smbpasswd')
            if tt == 0:
                break
            else:
                # Dans certaines distributions SuSE Linux, le script
mksmbpasswd
                # n'est pas accessible par défaut. L'installer si nécessaire
:
                print "** Script mksmbpasswd.sh inactif - Essai
d'installation : "
                tt = os.system('cp /usr/lib/samba/scripts/mksmbpasswd.sh
/usr/local/bin')
                if tt == 0:
                    tt = os.system('chmod 500
/usr/local/bin/mksmbpasswd.sh')
                    if tt == 0:
                        print "OK - Script installé et fonctionnel."
                    else:
                        print "** Script installé mais pas exécutable ???"
                        sys.exit()
                else:
                    print "** Script introuvable - Veuillez l'installer
manuellement."
                    sys.exit()
        os.chmod('/etc/private/smbpasswd', 0600)
        print "OK - Base de données smbpasswd à présent installée."
    # Suppression de la ligne correspondant aux comptes NIS (éventuelle) :
    #deleteLine('+', '/etc/private/smbpasswd')
    scanUsers(1)        # création des groupes
    print
    scanUsers(2)        # création des utilisateurs
    if quotas =='o':
        print
        scanUsers(4)    # établissement des quota

elif choix =='s':
    print '''
***** !! ATTENTION !! **********************************************
*  Toutes les données contenues dans les répertoires personnels    *
* de ces élèves seront effacées sans possibilité de récupération ! *
********************************************** !! ATTENTION !! *****
'''
    confirm = raw_input("Confirmez-vous l'effacement (o/n) ?")
    if confirm =='o':
        savepasswords()    # sauvegarde préalable des fichiers passwd
        scanUsers(5)       # suppression des utilisateurs (les groupes
restent).
        print "Les groupes ci-dessous doivent-ils aussi être effacés :"
        for g in grpList:
            print g,
        print
        delgr = raw_input("Effacer ces groupes (o/n) ? ")
        if delgr =='o':
            for group in grpList:
                deleteDirectory('/home/' + group)
                deleteDirectory('/home/siteweb/' + group)
                if exists('/home/' + group) or exists('/home/siteweb/' +
group):
                    # Ne pas supprimer le groupe si l'un ou l'autre des
                    # répertoires correspondants n'a pas été effacé
                    print "Le groupe %s n'a pas été supprimé." % (group)
                else:
                    os.system('smbpasswd -d ' + string.lower(group))
                    if exists('/etc/private/smbpasswd'):
                        deleteLine(string.lower(group),
'/etc/private/smbpasswd')
                    os.system('userdel ' + string.lower(group))
                    os.system('groupdel ' + group)

print '''
Job terminé.
'''






---------------------------------------------------------------------
Aide sur la liste: <URL:mailto:linux-31-help@CULTe.org>Le CULTe sur le web: <URL:http://www.CULTe.org/>