(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/>