#!/usr/bin/env python # -*- mode: python -*- # Copyright (c) 1999 Jason Gunthorpe # Copyright (c) 2003 James Troup # Copyright (c) 2004 Joey Schulze # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. # Imports passwd, shadow and group files into the directory. # You should cleanse the files of anything you do not want to add to the # directory. # # The first step is to call this script to import the passwd file and # create all the new entries. This should be done on an empty freshly # initialized directory with the rootdn/password set in the server. # The command to execute is # ldapimport -a -p ~/passwd # The -a tells the script to add all the entries it finds, it should be # used only once. # # The next step is to import the shadow file and group, no clensing need be # done for # this as any entries that do not exist will be ignored (silently) # ldapimport -s /etc/shadow -g /etc/group # import re, time, ldap, getopt, sys; from userdir_ldap import *; DoAdd = 0; WritePasses = 1; Passwd = ""; Shadow = ""; Group = ""; # This parses a gecos field and returns a tuple containing the new normalized # field and the first, middle and last name of the user. Gecos is formed # in the standard debian manner with 5 feilds seperated by commas def ParseGecos(Field): Gecos = re.split("[,:]",Field); cn = ""; mn = ""; sn = ""; if (len(Gecos) >= 1): (cn,mn,sn) = NameSplit(Gecos[0]); # Normalize the gecos field if (len(Gecos) > 5): Gecos = Gecos[0:4]; else: while (len(Gecos) < 5): Gecos.append(""); else: Gecos = ["","","","",""]; # Reconstruct the gecos after mauling it Field = Gecos[0] + "," + Gecos[1] + "," + Gecos[2] + "," + \ Gecos[3] + "," + Gecos[4]; return (Field,cn,mn,sn); # Read the passwd file into the database def DoPasswd(l,Passwd): # Read the passwd file and import it Passwd = open(Passwd,"r"); Outstanding = 0; while(1): Line = Passwd.readline(); if Line == "": break; Split = re.split("[:\n]",Line); (Split[4],cn,mn,sn) = ParseGecos(Split[4]); # This just tests whether these are integers and throws an # exception if not int(Split[2]) int(Split[3]) Rec = [("uid",Split[0]), ("uidNumber",Split[2]), ("gidNumber",Split[3]), ("gecos",Split[4]), ("homeDirectory",Split[5]), ("loginShell",Split[6]), ("cn",cn), ("sn",sn)]; # Avoid schema check complaints when mn is empty if (mn): Rec.append(("mn",mn)) Dn = "uid=" + Split[0] + "," + BaseDn; print "Importing", Dn sys.stdout.flush(); DoModify = True if (DoAdd == 1): try: AddRec = Rec[:] AddRec.append(("objectClass", UserObjectClasses)) l.add_s(Dn,AddRec) DoModify = False except ldap.ALREADY_EXISTS: print "exists",; if (DoModify): # Send the modify request ModRec = [(ldap.MOD_REPLACE, k[0], k[1]) for k in Rec] l.modify(Dn,ModRec); Outstanding = Outstanding + 1; Outstanding = FlushOutstanding(l,Outstanding,1); print "done"; FlushOutstanding(l,Outstanding); # Read the shadow file into the database def DoShadow(l,Shadow): # Read the passwd file and import it Shadow = open(Shadow,"r"); Outstanding = 0; while(1): Line = Shadow.readline(); if Line == "": break; Split = re.split("[:\n]",Line); # Ignore system accounts with no password, they do not belong in the # directory. if (Split[1] == 'x' or Split[1] == '*'): print "Ignoring system account,",Split[0]; continue; for x in range(2,8): int(Split[x]) Rec = [(ldap.MOD_REPLACE,"shadowLastChange",Split[2]), (ldap.MOD_REPLACE,"shadowMin",Split[3]), (ldap.MOD_REPLACE,"shadowMax",Split[4]), (ldap.MOD_REPLACE,"shadowWarning",Split[5])] # Avoid schema violations if (Split[6]): Rec.append((ldap.MOD_REPLACE,"shadowInactive",Split[6])) if (Split[7]): Rec.append((ldap.MOD_REPLACE,"shadowExpire",Split[7])) if (WritePasses == 1): Rec.append((ldap.MOD_REPLACE,"userPassword","{crypt}"+Split[1])); Dn = "uid=" + Split[0] + "," + BaseDn; print "Importing",Dn, sys.stdout.flush(); # Send the modify request l.modify(Dn,Rec); Outstanding = Outstanding + 1; print "done"; Outstanding = FlushOutstanding(l,Outstanding,1); FlushOutstanding(l,Outstanding); # Read the group file into the database def DoGroup(l,Group): # Read the passwd file and import it Group = open(Group,"r"); Outstanding = 0; while(1): Line = Group.readline(); if Line == "": break; # Split up the group information Split = re.split("[:\n]",Line); Members = re.split("[, ]*",Split[3]); int(Split[2]) # Iterate over the membership list and add the membership information # To the directory Rec = [(ldap.MOD_ADD,"supplementaryGid",Split[0])]; Counter = 0; for x in Members: if x == "": continue; Dn = "uid=" + x + "," + BaseDn; print "Adding",Dn,"to group",Split[0]; Counter = Counter+1; # Send the modify request l.modify(Dn,Rec); Outstanding = Outstanding + 1; Outstanding = FlushOutstanding(l,Outstanding,1); if Counter == 0: continue; Rec = [(ldap.MOD_REPLACE,"gid",Split[0]), (ldap.MOD_REPLACE,"gidNumber",Split[2])]; Dn = "gid=" + Split[0] + "," + BaseDn; print "Importing",Dn, sys.stdout.flush(); # Unfortunately add_s does not take the same args as modify :| if (DoAdd == 1): try: l.add_s(Dn,[("gid",Split[0]), ("objectClass", GroupObjectClasses)]) except ldap.ALREADY_EXISTS: print "exists",; # Send the modify request l.modify(Dn,Rec); Outstanding = Outstanding + 1; print "."; FlushOutstanding(l,Outstanding); # Process options (options, arguments) = getopt.getopt(sys.argv[1:], "ap:s:g:xu:") for (switch, val) in options: if (switch == '-a'): DoAdd = 1; if (switch == '-x'): WritePasses = 0; elif (switch == '-p'): Passwd = val elif (switch == '-s'): Shadow = val elif (switch == '-g'): Group = val elif (switch == '-u'): AdminUser = val # Main program starts here # Connect to the ldap server l = passwdAccessLDAP(BaseDn, AdminUser) if (Passwd != ""): DoPasswd(l,Passwd); if (Shadow != ""): DoShadow(l,Shadow); if (Group != ""): DoGroup(l,Group);