X-Git-Url: https://git.adam-barratt.org.uk/?a=blobdiff_plain;f=ud-generate;h=b20e6bb1756f0cdb7d5b90fcc85638e8202f9ec0;hb=db36cbb61b95f316e9f9bc0d89aea2d3bef3dc54;hp=def318686242a6abb8ee4bc3a850241ff5bb39bf;hpb=068a588b206be799352a8113e7ac5627500649e2;p=mirror%2Fuserdir-ldap.git diff --git a/ud-generate b/ud-generate index def3186..b20e6bb 100755 --- a/ud-generate +++ b/ud-generate @@ -2,7 +2,7 @@ # -*- mode: python -*- # Generates passwd, shadow and group files from the ldap directory. -import string, re, time, ldap, getopt, sys, os, posix, pwd; +import string, re, time, ldap, getopt, sys, os, pwd, posix; from userdir_ldap import *; PasswdAttrs = None; @@ -10,9 +10,16 @@ GroupIDMap = {}; Allowed = None; CurrentHost = ""; +EmailCheck = re.compile("^([^ <>@]+@[^ ,<>@]+)?$"); + def Sanitize(Str): return string.translate(Str,string.maketrans("\n\r\t","$$$")); +def DoLink(From,To,File): + try: posix.remove(To+File); + except: pass; + posix.link(From+File,To+File); + # See if this user is in the group list def IsInGroup(DnRecord): global Allowed,CurrentHost; @@ -39,7 +46,7 @@ def IsInGroup(DnRecord): return 1; return 0; -def Die(F,Fdb): +def Die(File,F,Fdb): if F != None: F.close(); if Fdb != None: @@ -91,7 +98,7 @@ def GenPasswd(l,File,HomePrefix): # Oops, something unspeakable happened. except: - Die(F,Fdb); + Die(File,F,Fdb); raise; Done(File,F,Fdb); @@ -133,7 +140,7 @@ def GenShadow(l,File): # Oops, something unspeakable happened. except: - Die(F,Fdb); + Die(File,F,Fdb); raise; Done(File,F,Fdb); @@ -144,7 +151,7 @@ def GenSSHShadow(l,File): try: OldMask = os.umask(0077); F = open(File + ".tmp","w",0600); - Fdb = None; + Fdb = os.popen("cdbmake %s.cdb %s.cdb.tmp"%(File,File),"w"); os.umask(OldMask); # Fetch all the users @@ -154,19 +161,23 @@ def GenSSHShadow(l,File): I = 0; for x in PasswdAttrs: - if x[1].has_key("uidnumber") == 0 or IsInGroup(x) == 0 or \ + if x[1].has_key("uidnumber") == 0 or \ x[1].has_key("sshrsaauthkey") == 0: continue; for I in x[1]["sshrsaauthkey"]: - Line = "%s: %s" %(GetAttr(x,"uid"),I); + User = GetAttr(x,"uid"); + Line = "%s: %s" %(User,I); Line = Sanitize(Line) + "\n"; F.write(Line); - + Fdb.write("+%d,%d:%s->%s\n"%(len(User),len(I),User,I)); + Fdb.write("\n"); # Oops, something unspeakable happened. except: - Die(F,Fdb); + Die(File,F,Fdb); raise; - Done(File,F,Fdb); + if Fdb.close() != None: + raise "cdbmake gave an error"; + Done(File,F,None); # Generate the group list def GenGroup(l,File): @@ -202,6 +213,8 @@ def GenGroup(l,File): # Output the group file. Counter = 0; for x in GroupMap.keys(): + if GroupIDMap.has_key(x) == 0: + continue; Line = "%s:x:%u:" % (x,GroupIDMap[x]); Comma = ''; for I in GroupMap[x]: @@ -216,7 +229,7 @@ def GenGroup(l,File): # Oops, something unspeakable happened. except: - Die(F,Fdb); + Die(File,F,Fdb); raise; Done(File,F,Fdb); @@ -227,7 +240,6 @@ def GenForward(l,File): try: OldMask = os.umask(0022); F = open(File + ".tmp","w",0644); - Fdb = None; os.umask(OldMask); # Fetch all the users @@ -244,16 +256,55 @@ def GenForward(l,File): if len(GetAttr(x,"emailforward")) > 200: continue; + # Check the forwarding address + if EmailCheck.match(GetAttr(x,"emailforward")) == None: + continue; Line = "%s: %s" % (GetAttr(x,"uid"),GetAttr(x,"emailforward")); Line = Sanitize(Line) + "\n"; F.write(Line); # Oops, something unspeakable happened. except: - Die(F,Fdb); + Die(File,F,Fdb); raise; Done(File,F,Fdb); +def GenAllForward(l,File): + Fdb = None; + try: + OldMask = os.umask(0022); + Fdb = os.popen("cdbmake %s %s.tmp"%(File,File),"w"); + os.umask(OldMask); + + # Fetch all the users + global PasswdAttrs; + if PasswdAttrs == None: + raise "No Users"; + + # Write out the email address for each user + for x in PasswdAttrs: + if x[1].has_key("emailforward") == 0: + continue; + + # Do not allow people to try to buffer overflow busted parsers + Forward = GetAttr(x,"emailforward"); + if len(Forward) > 200: + continue; + + # Check the forwarding address + if EmailCheck.match(Forward) == None: + continue; + + User = GetAttr(x,"uid"); + Fdb.write("+%d,%d:%s->%s\n"%(len(User),len(Forward),User,Forward)); + Fdb.write("\n"); + # Oops, something unspeakable happened. + except: + Fdb.close(); + raise; + if Fdb.close() != None: + raise "cdbmake gave an error"; + # Generate the anon XEarth marker file def GenMarkers(l,File): F = None; @@ -280,10 +331,53 @@ def GenMarkers(l,File): # Oops, something unspeakable happened. except: - Die(F,Fdb); + Die(File,F,Fdb); raise; Done(File,F,Fdb); - + +# Generate the debian-private subscription list +def GenPrivate(l,File): + F = None; + Fdb = None; + try: + F = open(File + ".tmp","w"); + Fdb = None; + + # Fetch all the users + global PasswdAttrs; + if PasswdAttrs == None: + raise "No Users"; + + # Write out the position for each user + for x in PasswdAttrs: + if x[1].has_key("privatesub") == 0: + continue; + + # If the account is locked, do not write it + if (string.find(GetAttr(x,"userpassword"),"*LK*") != -1): + continue; + + # If the account has no PGP key, do not write it + if x[1].has_key("keyfingerprint") == 0: + continue; + + # Must be in the Debian group (yuk, hard coded for now) + if GetAttr(x,"gidnumber") != "800": + continue; + + try: + Line = "%s"%(GetAttr(x,"privatesub")); + Line = Sanitize(Line) + "\n"; + F.write(Line); + except: + pass; + + # Oops, something unspeakable happened. + except: + Die(File,F,Fdb); + raise; + Done(File,F,Fdb); + # Generate the DNS Zone file def GenDNS(l,File): F = None; @@ -305,25 +399,36 @@ def GenDNS(l,File): F.write("; %s\n"%(EmailAddress(x))); for z in x[1]["dnszoneentry"]: Split = string.split(string.lower(z)); - for y in range(0,len(Split)): - if Split[y] == "$": - Split[y] = "\n\t"; - - Line = string.join(Split," ") + "\n"; - F.write(Line); + if string.lower(Split[1]) == 'in': + for y in range(0,len(Split)): + if Split[y] == "$": + Split[y] = "\n\t"; + Line = string.join(Split," ") + "\n"; + F.write(Line); + + # Write some identication information + if string.lower(Split[2]) == "a": + Line = "%s IN TXT \"%s\"\n"%(Split[0],EmailAddress(x)); + for y in x[1]["keyfingerprint"]: + Line = Line + "%s IN TXT \"PGP %s\"\n"%(Split[0],FormatPGPKey(y)); + F.write(Line); + else: + Line = "; Err %s"%(str(Split)); + F.write(Line); + F.write("\n"); except: pass; # Oops, something unspeakable happened. except: - Die(F,Fdb); + Die(File,F,Fdb); raise; Done(File,F,Fdb); # Connect to the ldap server l = ldap.open(LDAPServer); -F = open(PassDir+"/pass-"+pwd.getpwuid(posix.getuid())[0],"r"); +F = open(PassDir+"/pass-"+pwd.getpwuid(os.getuid())[0],"r"); Pass = string.split(string.strip(F.readline())," "); F.close(); l.simple_bind_s("uid="+Pass[0]+","+BaseDn,Pass[1]); @@ -345,13 +450,26 @@ PasswdAttrs = l.search_s(BaseDn,ldap.SCOPE_ONELEVEL,"uid=*",\ "gecos","loginshell","userpassword","shadowlastchange",\ "shadowmin","shadowmax","shadowwarning","shadowinactive", "shadowexpire","emailforward","latitude","longitude",\ - "allowedhosts","sshrsaauthkey","dnszoneentry","cn","sn"]); + "allowedhosts","sshrsaauthkey","dnszoneentry","cn","sn",\ + "keyfingerprint","privatesub"]); # Open the control file if len(sys.argv) == 1: F = open(GenerateConf,"r"); else: F = open(sys.argv[1],"r") + +# Generate global things +GlobalDir = GenerateDir+"/"; +GenSSHShadow(l,GlobalDir+"ssh-rsa-shadow"); +GenAllForward(l,GlobalDir+"mail-forward.cdb"); +GenMarkers(l,GlobalDir+"markers"); +GenDNS(l,GlobalDir+"dns-zone"); +GenPrivate(l,GlobalDir+"debian-private"); + +# Compatibility. +GenForward(l,GlobalDir+"forward-alias"); + while(1): Line = F.readline(); if Line == "": @@ -382,13 +500,23 @@ while(1): Allowed = GroupList; CurrentHost = Split[0]; + sys.stdout.flush(); GenPasswd(l,OutDir+"passwd",Split[1]); + sys.stdout.flush(); GenGroup(l,OutDir+"group"); GenShadow(l,OutDir+"shadow"); - GenSSHShadow(l,OutDir+"ssh-rsa-shadow"); - GenForward(l,OutDir+"forward-alias"); - GenMarkers(l,OutDir+"markers"); + + # Link in global things + DoLink(GlobalDir,OutDir,"ssh-rsa-shadow"); + DoLink(GlobalDir,OutDir,"ssh-rsa-shadow.cdb"); + DoLink(GlobalDir,OutDir,"markers"); + DoLink(GlobalDir,OutDir,"mail-forward.cdb"); - if ExtraList.has_key("[DNS]"): - GenDNS(l,OutDir+"dns-zone"); + # Compatibility. + DoLink(GlobalDir,OutDir,"forward-alias"); + if ExtraList.has_key("[DNS]"): + DoLink(GlobalDir,OutDir,"dns-zone"); + + if ExtraList.has_key("[PRIVATE]"): + DoLink(GlobalDir,OutDir,"debian-private");