Initial import
[mirror/userdir-ldap.git] / ud-generate
1 #!/usr/bin/env python
2 # -*- mode: python -*-
3 # Generates passwd, shadow and group files from the ldap directory.
4
5 import string, re, time, ldap, getopt, sys, os, posix, pwd;
6 from userdir_ldap import *;
7
8 PasswdAttrs = None;
9 GroupIDMap = {};
10
11 # See if this user is in the group list
12 def IsInGroup(DnRecord,Allowed):
13   # See if the primary group is in the list
14   if Allowed.has_key(GetAttr(DnRecord,"gidnumber")) != 0:
15      return 1;
16
17   # See if there are supplementary groups
18   if DnRecord[1].has_key("supplementarygid") == 0:
19      return 0;
20
21   # Check the supplementary groups
22   for I in DnRecord[1]["supplementarygid"]:
23      if Allowed.has_key(I):
24         return 1;
25   return 0;
26
27 def Die(F,Fdb):
28    if F != None:
29       F.close();
30    if Fdb != None:
31       Fdb.close();
32    try: os.remove(File + ".tmp");
33    except: pass;
34    try: os.remove(File + ".tdb.tmp");
35    except: pass;
36
37 def Done(File,F,Fdb):
38   if F != None:
39     F.close();
40     os.rename(File + ".tmp",File);
41   if Fdb != None:
42     Fdb.close();
43     os.rename(File + ".tdb.tmp",File+".tdb");
44   
45 # Generate the password list
46 def GenPasswd(l,File,HomePrefix,Allowed):
47   F = None;
48   Fdb = None;
49   try:
50    F = open(File + ".tmp","w");
51    Fdb = open(File + ".tdb.tmp","w");
52
53    # Fetch all the users
54    global PasswdAttrs;
55    if PasswdAttrs == None:
56       raise "No Users";
57
58    I = 0;
59    for x in PasswdAttrs:
60       if x[1].has_key("uidnumber") == 0 or IsInGroup(x,Allowed) == 0:
61          continue;
62             
63       Line = "%s:x:%s:%s:%s:%s%s:%s\n" % (GetAttr(x,"uid"),\
64               GetAttr(x,"uidnumber"),GetAttr(x,"gidnumber"),\
65               GetAttr(x,"gecos"),HomePrefix,GetAttr(x,"uid"),\
66               GetAttr(x,"loginshell"));
67       F.write(Line);
68       Fdb.write("0%u %s" % (I,Line));
69       Fdb.write(".%s %s" % (GetAttr(x,"uid"),Line));
70       Fdb.write("=%s %s" % (GetAttr(x,"uidnumber"),Line));
71       I = I + 1;
72
73   # Oops, something unspeakable happened.
74   except:
75    Die(F,Fdb);
76    raise;
77   Done(File,F,Fdb);
78
79 # Generate the shadow list
80 def GenShadow(l,File,Allowed):
81   F = None;
82   Fdb = None;
83   try:
84    OldMask = os.umask(0077);
85    F = open(File + ".tmp","w",0600);
86    Fdb = open(File + ".tdb.tmp","w",0600);
87    os.umask(OldMask);
88
89    # Fetch all the users
90    global PasswdAttrs;
91    if PasswdAttrs == None:
92       raise "No Users";
93
94    I = 0;
95    for x in PasswdAttrs:
96       if x[1].has_key("uidnumber") == 0 or IsInGroup(x,Allowed) == 0:
97          continue;
98          
99       Pass = GetAttr(x,"userpassword");
100       if Pass[0:7] != "{crypt}":
101          Pass = '*';
102       else:
103          Pass = Pass[7:];
104       Line = "%s:%s:%s:%s:%s:%s:%s:%s:\n" % (GetAttr(x,"uid"),\
105               Pass,GetAttr(x,"shadowlastchange"),\
106               GetAttr(x,"shadowmin"),GetAttr(x,"shadowmax"),\
107               GetAttr(x,"shadowwarning"),GetAttr(x,"shadowinactive"),\
108               GetAttr(x,"shadowexpire"));
109       F.write(Line);
110       Fdb.write("0%u %s" % (I,Line));
111       Fdb.write(".%s %s" % (GetAttr(x,"uid"),Line));
112       I = I + 1;
113
114   # Oops, something unspeakable happened.
115   except:
116    Die(F,Fdb);
117    raise;
118   Done(File,F,Fdb);
119
120 # Generate the group list
121 def GenGroup(l,File,Allowed):
122   F = None;
123   Fdb = None;
124   try:
125    F = open(File + ".tmp","w");
126    Fdb = open(File + ".tdb.tmp","w");
127
128    # Generate the GroupMap
129    GroupMap = {};
130    for x in GroupIDMap.keys():
131       GroupMap[x] = [];
132       
133    # Fetch all the users
134    global PasswdAttrs;
135    if PasswdAttrs == None:
136       raise "No Users";
137
138    # Sort them into a list of groups having a set of users
139    for x in PasswdAttrs:
140       if x[1].has_key("uidnumber") == 0 or IsInGroup(x,Allowed) == 0:
141          continue;
142       if x[1].has_key("supplementarygid") == 0:
143          continue;
144          
145       for I in x[1]["supplementarygid"]:
146          if GroupMap.has_key(I):
147             GroupMap[I].append(GetAttr(x,"uid"));
148          else:
149             GroupMap[I] = [GetAttr(x,"uid")];
150             
151    # Output the group file.
152    Counter = 0; 
153    for x in GroupMap.keys():
154       Line = "%s:x:%u:" % (x,GroupIDMap[x]);
155       Comma = '';
156       for I in GroupMap[x]:
157         Line = Line + ("%s%s" % (Comma,I));
158         Comma = ',';
159       Line = Line + '\n';
160       F.write(Line);
161       Fdb.write("0%u %s" % (Counter,Line));
162       Fdb.write(".%s %s" % (x,Line));
163       Fdb.write("=%u %s" % (GroupIDMap[x],Line));
164       Counter = Counter + 1;
165       
166   # Oops, something unspeakable happened.
167   except:
168    Die(F,Fdb);
169    raise;
170   Done(File,F,Fdb);
171
172 # Generate the email forwarding list
173 def GenForward(l,File,Allowed):
174   F = None;
175   Fdb = None;
176   try:
177    F = open(File + ".tmp","w");
178    Fdb = None;
179
180    # Fetch all the users
181    global PasswdAttrs;
182    if PasswdAttrs == None:
183       raise "No Users";
184
185    # Write out the email address for each user
186    for x in PasswdAttrs:
187       if x[1].has_key("emailforward") == 0 or IsInGroup(x,Allowed) == 0:
188          continue;
189       Line = "%s: %s\n" % (GetAttr(x,"uid"),GetAttr(x,"emailforward"));
190       F.write(Line);
191       
192   # Oops, something unspeakable happened.
193   except:
194    Die(F,Fdb);
195    raise;
196   Done(File,F,Fdb);
197
198 # Connect to the ldap server
199 l = ldap.open(LDAPServer);
200 F = open(PassDir+"/pass-"+pwd.getpwuid(posix.getuid())[0],"r");
201 Pass = string.split(string.strip(F.readline())," ");
202 F.close();
203 l.simple_bind_s("uid="+Pass[0]+","+BaseDn,Pass[1]);
204
205 # Fetch all the groups
206 GroupIDMap = {};
207 Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"gid=*",\
208                   ["gid","gidnumber"]);
209
210 # Generate the GroupMap and GroupIDMap
211 for x in Attrs:
212    if x[1].has_key("gidnumber") == 0:
213       continue;
214    GroupIDMap[x[1]["gid"][0]] = int(x[1]["gidnumber"][0]);
215
216 # Fetch all the users
217 PasswdAttrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"uid=*",\
218                 ["uid","uidnumber","gidnumber","supplementarygid",\
219                  "gecos","loginshell","userpassword","shadowlastchange",\
220                  "shadowmin","shadowmax","shadowwarning","shadowinactive",
221                  "shadowexpire","emailforward"]);
222
223 # Open the control file
224 if len(sys.argv) == 1:
225    F = open(GenerateConf,"r");
226 else:
227    F = open(sys.argv[1],"r")
228 while(1):
229    Line = F.readline();
230    if Line == "":
231       break;
232    Line = string.strip(Line);
233    if Line == "":
234       continue;
235    if Line[0] == '#':
236       continue;
237
238    Split = string.split(Line," ");
239    OutDir = GenerateDir + '/' + Split[0] + '/';
240    try: os.mkdir(OutDir);
241    except: pass;
242
243    # Get the group list and convert any named groups to numerics
244    GroupList = {};
245    for I in Split[2:]:
246       GroupList[I] = None;
247       if GroupIDMap.has_key(I):
248          GroupList[str(GroupIDMap[I])] = None;
249
250    GenPasswd(l,OutDir+"passwd",Split[1],GroupList);
251    GenGroup(l,OutDir+"group",GroupList);
252    GenShadow(l,OutDir+"shadow",GroupList);
253    GenForward(l,OutDir+"forward-alias",GroupList);