3 # Generates passwd, shadow and group files from the ldap directory.
5 import string, re, time, ldap, getopt, sys, os, pwd, posix;
6 from userdir_ldap import *;
14 return string.translate(Str,string.maketrans("\n\r\t","$$$"));
16 def DoLink(From,To,File):
17 try: posix.remove(To+File);
19 posix.link(From+File,To+File);
21 # See if this user is in the group list
22 def IsInGroup(DnRecord):
23 global Allowed,CurrentHost;
27 # See if the primary group is in the list
28 if Allowed.has_key(GetAttr(DnRecord,"gidnumber")) != 0:
31 # Check the host based ACL
32 if DnRecord[1].has_key("allowedhosts") != 0:
33 for I in DnRecord[1]["allowedhosts"]:
37 # See if there are supplementary groups
38 if DnRecord[1].has_key("supplementarygid") == 0:
41 # Check the supplementary groups
42 for I in DnRecord[1]["supplementarygid"]:
43 if Allowed.has_key(I):
52 try: os.remove(File + ".tmp");
54 try: os.remove(File + ".tdb.tmp");
60 os.rename(File + ".tmp",File);
63 os.rename(File + ".tdb.tmp",File+".tdb");
65 # Generate the password list
66 def GenPasswd(l,File,HomePrefix):
70 F = open(File + ".tmp","w");
71 Fdb = open(File + ".tdb.tmp","w");
75 if PasswdAttrs == None:
80 if x[1].has_key("uidnumber") == 0 or IsInGroup(x) == 0:
83 # Do not let people try to buffer overflow some busted passwd parser.
84 if len(GetAttr(x,"gecos")) > 100 or len(GetAttr(x,"loginshell")) > 50:
87 Line = "%s:x:%s:%s:%s:%s%s:%s\n" % (GetAttr(x,"uid"),\
88 GetAttr(x,"uidnumber"),GetAttr(x,"gidnumber"),\
89 GetAttr(x,"gecos"),HomePrefix,GetAttr(x,"uid"),\
90 GetAttr(x,"loginshell"));
92 Fdb.write("0%u %s" % (I,Line));
93 Fdb.write(".%s %s" % (GetAttr(x,"uid"),Line));
94 Fdb.write("=%s %s" % (GetAttr(x,"uidnumber"),Line));
97 # Oops, something unspeakable happened.
103 # Generate the shadow list
104 def GenShadow(l,File):
108 OldMask = os.umask(0077);
109 F = open(File + ".tmp","w",0600);
110 Fdb = open(File + ".tdb.tmp","w",0600);
113 # Fetch all the users
115 if PasswdAttrs == None:
119 for x in PasswdAttrs:
120 if x[1].has_key("uidnumber") == 0 or IsInGroup(x) == 0:
123 Pass = GetAttr(x,"userpassword");
124 if Pass[0:7] != "{crypt}" or len(Pass) > 50:
128 Line = "%s:%s:%s:%s:%s:%s:%s:%s:" % (GetAttr(x,"uid"),\
129 Pass,GetAttr(x,"shadowlastchange"),\
130 GetAttr(x,"shadowmin"),GetAttr(x,"shadowmax"),\
131 GetAttr(x,"shadowwarning"),GetAttr(x,"shadowinactive"),\
132 GetAttr(x,"shadowexpire"));
133 Line = Sanitize(Line) + "\n";
135 Fdb.write("0%u %s" % (I,Line));
136 Fdb.write(".%s %s" % (GetAttr(x,"uid"),Line));
139 # Oops, something unspeakable happened.
145 # Generate the shadow list
146 def GenSSHShadow(l,File):
150 OldMask = os.umask(0077);
151 F = open(File + ".tmp","w",0600);
152 Fdb = os.popen("cdbmake %s.cdb %s.cdb.tmp"%(File,File),"w");
155 # Fetch all the users
157 if PasswdAttrs == None:
161 for x in PasswdAttrs:
162 if x[1].has_key("uidnumber") == 0 or \
163 x[1].has_key("sshrsaauthkey") == 0:
165 for I in x[1]["sshrsaauthkey"]:
166 User = GetAttr(x,"uid");
167 Line = "%s: %s" %(User,I);
168 Line = Sanitize(Line) + "\n";
170 Fdb.write("+%d,%d:%s->%s\n"%(len(User),len(I),User,I));
172 # Oops, something unspeakable happened.
176 if Fdb.close() != None:
177 raise "cdbmake gave an error";
180 # Generate the group list
181 def GenGroup(l,File):
185 F = open(File + ".tmp","w");
186 Fdb = open(File + ".tdb.tmp","w");
188 # Generate the GroupMap
190 for x in GroupIDMap.keys():
193 # Fetch all the users
195 if PasswdAttrs == None:
198 # Sort them into a list of groups having a set of users
199 for x in PasswdAttrs:
200 if x[1].has_key("uidnumber") == 0 or IsInGroup(x) == 0:
202 if x[1].has_key("supplementarygid") == 0:
205 for I in x[1]["supplementarygid"]:
206 if GroupMap.has_key(I):
207 GroupMap[I].append(GetAttr(x,"uid"));
209 print "Group does not exist ",I,"but",GetAttr(x,"uid"),"is in it";
211 # Output the group file.
213 for x in GroupMap.keys():
214 if GroupIDMap.has_key(x) == 0:
216 Line = "%s:x:%u:" % (x,GroupIDMap[x]);
218 for I in GroupMap[x]:
219 Line = Line + ("%s%s" % (Comma,I));
221 Line = Sanitize(Line) + "\n";
223 Fdb.write("0%u %s" % (Counter,Line));
224 Fdb.write(".%s %s" % (x,Line));
225 Fdb.write("=%u %s" % (GroupIDMap[x],Line));
226 Counter = Counter + 1;
228 # Oops, something unspeakable happened.
234 # Generate the email forwarding list
235 def GenForward(l,File):
239 OldMask = os.umask(0022);
240 F = open(File + ".tmp","w",0644);
243 # Fetch all the users
245 if PasswdAttrs == None:
248 # Write out the email address for each user
249 for x in PasswdAttrs:
250 if x[1].has_key("emailforward") == 0 or IsInGroup(x) == 0:
253 # Do not allow people to try to buffer overflow busted parsers
254 if len(GetAttr(x,"emailforward")) > 200:
257 Line = "%s: %s" % (GetAttr(x,"uid"),GetAttr(x,"emailforward"));
258 Line = Sanitize(Line) + "\n";
261 # Oops, something unspeakable happened.
267 def GenAllForward(l,File):
270 OldMask = os.umask(0022);
271 Fdb = os.popen("cdbmake %s %s.tmp"%(File,File),"w");
274 # Fetch all the users
276 if PasswdAttrs == None:
279 # Write out the email address for each user
280 for x in PasswdAttrs:
281 if x[1].has_key("emailforward") == 0:
284 # Do not allow people to try to buffer overflow busted parsers
285 Forward = GetAttr(x,"emailforward");
286 if len(Forward) > 200:
289 User = GetAttr(x,"uid");
290 Fdb.write("+%d,%d:%s->%s\n"%(len(User),len(Forward),User,Forward));
292 # Oops, something unspeakable happened.
296 if Fdb.close() != None:
297 raise "cdbmake gave an error";
299 # Generate the anon XEarth marker file
300 def GenMarkers(l,File):
304 F = open(File + ".tmp","w");
307 # Fetch all the users
309 if PasswdAttrs == None:
312 # Write out the position for each user
313 for x in PasswdAttrs:
314 if x[1].has_key("latitude") == 0 or x[1].has_key("longitude") == 0:
317 Line = "%8s %8s \"\""%(DecDegree(GetAttr(x,"latitude"),1),DecDegree(GetAttr(x,"longitude"),1));
318 Line = Sanitize(Line) + "\n";
323 # Oops, something unspeakable happened.
329 # Generate the debian-private subscription list
330 def GenPrivate(l,File):
334 F = open(File + ".tmp","w");
337 # Fetch all the users
339 if PasswdAttrs == None:
342 # Write out the position for each user
343 for x in PasswdAttrs:
344 if x[1].has_key("privatesub") == 0:
347 # If the account is locked, do not write it
348 if (string.find(GetAttr(x,"userpassword"),"*LK*") != -1):
351 # If the account has no PGP key, do not write it
352 if x[1].has_key("keyfingerprint") == 0:
355 # Must be in the Debian group (yuk, hard coded for now)
356 if GetAttr(x,"gidnumber") != "800":
360 Line = "%s"%(GetAttr(x,"privatesub"));
361 Line = Sanitize(Line) + "\n";
366 # Oops, something unspeakable happened.
372 # Generate the DNS Zone file
377 F = open(File + ".tmp","w");
380 # Fetch all the users
382 if PasswdAttrs == None:
385 # Write out the zone file entry for each user
386 for x in PasswdAttrs:
387 if x[1].has_key("dnszoneentry") == 0:
390 F.write("; %s\n"%(EmailAddress(x)));
391 for z in x[1]["dnszoneentry"]:
392 Split = string.split(string.lower(z));
393 if string.lower(Split[1]) == 'in':
394 for y in range(0,len(Split)):
397 Line = string.join(Split," ") + "\n";
400 # Write some identication information
401 if string.lower(Split[2]) != "cname":
402 Line = "%s IN TXT \"%s\"\n"%(Split[0],EmailAddress(x));
403 for y in x[1]["keyfingerprint"]:
404 Line = Line + "%s IN TXT \"PGP %s\"\n"%(Split[0],FormatPGPKey(y));
407 Line = "; Err %s"%(str(Split));
414 # Oops, something unspeakable happened.
420 # Connect to the ldap server
421 l = ldap.open(LDAPServer);
422 F = open(PassDir+"/pass-"+pwd.getpwuid(os.getuid())[0],"r");
423 Pass = string.split(string.strip(F.readline())," ");
425 l.simple_bind_s("uid="+Pass[0]+","+BaseDn,Pass[1]);
427 # Fetch all the groups
429 Attrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"gid=*",\
430 ["gid","gidnumber"]);
432 # Generate the GroupMap and GroupIDMap
434 if x[1].has_key("gidnumber") == 0:
436 GroupIDMap[x[1]["gid"][0]] = int(x[1]["gidnumber"][0]);
438 # Fetch all the users
439 PasswdAttrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"uid=*",\
440 ["uid","uidnumber","gidnumber","supplementarygid",\
441 "gecos","loginshell","userpassword","shadowlastchange",\
442 "shadowmin","shadowmax","shadowwarning","shadowinactive",
443 "shadowexpire","emailforward","latitude","longitude",\
444 "allowedhosts","sshrsaauthkey","dnszoneentry","cn","sn",\
445 "keyfingerprint","privatesub"]);
447 # Open the control file
448 if len(sys.argv) == 1:
449 F = open(GenerateConf,"r");
451 F = open(sys.argv[1],"r")
453 # Generate global things
454 GlobalDir = GenerateDir+"/";
455 GenSSHShadow(l,GlobalDir+"ssh-rsa-shadow");
456 GenAllForward(l,GlobalDir+"mail-forward.cdb");
457 GenMarkers(l,GlobalDir+"markers");
458 GenDNS(l,GlobalDir+"dns-zone");
459 GenPrivate(l,GlobalDir+"debian-private");
462 GenForward(l,GlobalDir+"forward-alias");
468 Line = string.strip(Line);
474 Split = string.split(Line," ");
475 OutDir = GenerateDir + '/' + Split[0] + '/';
476 try: os.mkdir(OutDir);
479 # Get the group list and convert any named groups to numerics
487 if GroupIDMap.has_key(I):
488 GroupList[str(GroupIDMap[I])] = None;
490 global Allowed,CurrentHost;
492 CurrentHost = Split[0];
495 GenPasswd(l,OutDir+"passwd",Split[1]);
497 GenGroup(l,OutDir+"group");
498 GenShadow(l,OutDir+"shadow");
500 # Link in global things
501 DoLink(GlobalDir,OutDir,"ssh-rsa-shadow");
502 DoLink(GlobalDir,OutDir,"ssh-rsa-shadow.cdb");
503 DoLink(GlobalDir,OutDir,"markers");
504 DoLink(GlobalDir,OutDir,"mail-forward.cdb");
507 DoLink(GlobalDir,OutDir,"forward-alias");
509 if ExtraList.has_key("[DNS]"):
510 DoLink(GlobalDir,OutDir,"dns-zone");
512 if ExtraList.has_key("[PRIVATE]"):
513 DoLink(GlobalDir,OutDir,"debian-private");