Initial import
[mirror/userdir-ldap.git] / ud-userimport
1 #!/usr/bin/env python
2 # -*- mode: python -*-
3 # Imports passwd, shadow and group files into the directory.
4 # You should cleanse the files of anything you do not want to add to the
5 # directory.
6 #
7 # The first step is to call this script to import the passwd file and
8 # create all the new entries. This should be done on an empty freshly 
9 # initialized directory with the rootdn/password set in the server.
10 # The command to execute is
11 #   ldapimport -a -p ~/passwd
12 # The -a tells the script to add all the entries it finds, it should be
13 # used only once.
14 #
15 # The next step is to import the shadow file and group, no clensing need be 
16 # done for 
17 # this as any entries that do not exist will be ignored (silently)
18 #  ldapimport -s /etc/shadow -g /etc/group
19
20
21 import string, re, time, ldap, getopt, sys;
22 from userdir_ldap import *;
23
24 DoAdd = 0;
25 WritePasses = 1;
26 Passwd = "";
27 Shadow = "";
28 Group = "";
29
30 # This parses a gecos field and returns a tuple containing the new normalized
31 # field and the first, middle and last name of the user. Gecos is formed
32 # in the standard debian manner with 5 feilds seperated by commas
33 def ParseGecos(Field):
34    Gecos = re.split("[,:]",Field);
35    cn = "";
36    mn = "";
37    sn = "";
38    if (len(Gecos) >= 1):
39       (cn,mn,sn) = NameSplit(Gecos[0]);
40
41       # Normalize the gecos field
42       if (len(Gecos) > 5):
43          Gecos = Gecos[0:4];
44       else:
45          while (len(Gecos) < 5):
46             Gecos.append("");
47    else:
48       Gecos = ["","","","",""];
49
50    # Reconstruct the gecos after mauling it
51    Field = Gecos[0] + "," + Gecos[1] + "," + Gecos[2] + "," + \
52            Gecos[3] + "," + Gecos[4];
53    return (Field,cn,mn,sn);
54
55 # Check if a number string is really a number
56 def CheckNumber(Num):
57    for x in Num:
58       string.index(string.digits,x);
59
60 # Read the passwd file into the database
61 def DoPasswd(l,Passwd):
62    # Read the passwd file and import it
63    Passwd = open(Passwd,"r");
64    Outstanding = 0;
65    while(1):
66       Line = Passwd.readline();
67       if Line == "":
68          break;
69
70       Split = re.split("[:\n]",Line);
71       (Split[4],cn,mn,sn) = ParseGecos(Split[4]);
72       CheckNumber(Split[2]);
73       CheckNumber(Split[3]);
74       Rec = [(ldap.MOD_REPLACE,"uid",Split[0]),
75              (ldap.MOD_REPLACE,"uidNumber",Split[2]),
76              (ldap.MOD_REPLACE,"gidNumber",Split[3]),
77              (ldap.MOD_REPLACE,"gecos",Split[4]),
78              (ldap.MOD_REPLACE,"homeDirectory",Split[5]),
79              (ldap.MOD_REPLACE,"loginShell",Split[6]),
80              (ldap.MOD_REPLACE,"cn",cn),
81              (ldap.MOD_REPLACE,"mn",mn),
82              (ldap.MOD_REPLACE,"sn",sn)];
83
84       Dn = "uid=" + Split[0] + "," + BaseDn;
85       print "Importing",Dn,
86       sys.stdout.flush();
87
88       # Unfortunately add_s does not take the same args as modify :|
89       if (DoAdd == 1):
90          try:
91             l.add_s(Dn,[("uid",Split[0]),
92                         ("objectclass","top"),
93                         ("objectclass","account"),
94                         ("objectclass","posixAccount"),
95                         ("objectclass","shadowAccount"),
96                         ("objectclass","debiandeveloper")]);
97          except ldap.ALREADY_EXISTS:
98             print "exists",;
99
100       # Send the modify request
101       l.modify(Dn,Rec);
102       Outstanding = Outstanding + 1;
103       Outstanding = FlushOutstanding(l,Outstanding,1);
104       print "done";
105    FlushOutstanding(l,Outstanding);
106
107 # Read the shadow file into the database
108 def DoShadow(l,Shadow):
109    # Read the passwd file and import it
110    Shadow = open(Shadow,"r");
111    Outstanding = 0;
112    while(1):
113       Line = Shadow.readline();
114       if Line == "":
115          break;
116
117       Split = re.split("[:\n]",Line);
118       
119       # Ignore system accounts with no password, they do not belong in the
120       # directory.
121       if (Split[1] == 'x' or Split[1] == '*'):
122          print "Ignoring system account,",Split[0];
123          continue;
124
125       for x in range(2,8):
126          CheckNumber(Split[x]);
127
128       Rec = [(ldap.MOD_REPLACE,"shadowLastChange",Split[2]),
129              (ldap.MOD_REPLACE,"shadowMin",Split[3]),
130              (ldap.MOD_REPLACE,"shadowMax",Split[4]),
131              (ldap.MOD_REPLACE,"shadowWarning",Split[5]),
132              (ldap.MOD_REPLACE,"shadowInactive",Split[6]),
133              (ldap.MOD_REPLACE,"shadowExpire",Split[7])];
134       if (WritePasses == 1):
135          Rec.append((ldap.MOD_REPLACE,"userPassword","{crypt}"+Split[1]));
136
137       Dn = "uid=" + Split[0] + "," + BaseDn;
138       print "Importing",Dn,
139       sys.stdout.flush();
140
141       # Send the modify request
142       l.modify(Dn,Rec);
143       Outstanding = Outstanding + 1;
144       print "done";
145       Outstanding = FlushOutstanding(l,Outstanding,1);
146    FlushOutstanding(l,Outstanding);
147
148 # Read the group file into the database
149 def DoGroup(l,Group):
150    # Read the passwd file and import it
151    Group = open(Group,"r");
152    Outstanding = 0;
153    while(1):
154       Line = Group.readline();
155       if Line == "":
156          break;
157
158       # Split up the group information
159       Split = re.split("[:\n]",Line);
160       Members = re.split("[, ]*",Split[3]);
161       CheckNumber(Split[2]);
162
163       # Iterate over the membership list and add the membership information
164       # To the directory
165       Rec = [(ldap.MOD_ADD,"supplementarygid",Split[0])];
166       Counter = 0;
167       for x in Members:
168          if x == "":
169             continue;
170             
171          Dn = "uid=" + x + "," + BaseDn;
172          print "Adding",Dn,"to group",Split[0];
173          Counter = Counter+1;
174
175          # Send the modify request
176          l.modify(Dn,Rec);
177          Outstanding = Outstanding + 1;
178          Outstanding = FlushOutstanding(l,Outstanding,1);
179          
180       if Counter == 0:
181          continue;
182
183       Rec = [(ldap.MOD_REPLACE,"gid",Split[0]),
184              (ldap.MOD_REPLACE,"gidNumber",Split[2])];
185
186       Dn = "gid=" + Split[0] + "," + BaseDn;
187       print "Importing",Dn,
188       sys.stdout.flush();
189
190       # Unfortunately add_s does not take the same args as modify :|
191       if (DoAdd == 1):
192          try:
193             l.add_s(Dn,[("gid",Split[0]),
194                         ("objectclass","top"),
195                         ("objectclass","posixGroup")]);
196          except ldap.ALREADY_EXISTS:
197             print "exists",;
198
199       # Send the modify request
200       l.modify(Dn,Rec);
201       Outstanding = Outstanding + 1;
202       print ".";
203
204    FlushOutstanding(l,Outstanding);
205
206 # Process options
207 (options, arguments) = getopt.getopt(sys.argv[1:], "ap:s:g:xu:")
208 for (switch, val) in options:
209    if (switch == '-a'):
210       DoAdd = 1;
211    if (switch == '-x'):
212       WritePasses = 0;
213    elif (switch == '-p'):
214       Passwd = val
215    elif (switch == '-s'):
216       Shadow = val
217    elif (switch == '-g'):
218       Group = val
219    elif (switch == '-u'):
220       AdminUser = val
221
222 # Main program starts here
223 print "Accessing LDAP directory as '" + AdminUser + "'";
224 Password = getpass(AdminUser + "'s password: ");
225
226 # Connect to the ldap server
227 l = ldap.open(LDAPServer);
228 UserDn = "uid=" + AdminUser + "," + BaseDn;
229 l.simple_bind_s(UserDn,Password);
230
231 if (Passwd != ""):
232    DoPasswd(l,Passwd);
233
234 if (Shadow != ""):
235    DoShadow(l,Shadow);
236
237 if (Group != ""):
238    DoGroup(l,Group);