default anti-spam options
[mirror/userdir-ldap.git] / ud-generate
index b60e171..1681e97 100755 (executable)
@@ -47,6 +47,8 @@ UUID_FORMAT = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
 EmailCheck = re.compile("^([^ <>@]+@[^ ,<>@]+)?$")
 BSMTPCheck = re.compile(".*mx 0 (master)\.debian\.org\..*",re.DOTALL)
 PurposeHostField = re.compile(r".*\[\[([\*\-]?[a-z0-9.\-]*)(?:\|.*)?\]\]")
+IsV6Addr = re.compile("^[a-fA-F0-9:]+$")
+IsDebianHost = re.compile("[a-zA-Z0-9\.]+\.debian\.org$")
 DNSZone = ".debian.net"
 Keyrings = ConfModule.sync_keyrings.split(":")
 
@@ -467,8 +469,8 @@ def GenGroup(File):
    return grouprevmap
 
 def CheckForward():
-   global DebianUsers
-   for x in DebianUsers:
+   global PasswdAttrs
+   for x in PasswdAttrs:
       if x[1].has_key("emailForward") == 0:
          continue
    
@@ -494,10 +496,10 @@ def GenForward(File):
       os.umask(OldMask)
      
       # Fetch all the users
-      global DebianUsers
+      global PasswdAttrs
      
       # Write out the email address for each user
-      for x in DebianUsers:
+      for x in PasswdAttrs:
          if x[1].has_key("emailForward") == 0:
             continue
      
@@ -511,18 +513,15 @@ def GenForward(File):
       raise
    Done(File, F, None)
 
-def GenCDB(File, Key):
+def GenCDB(File, Users, Key):
    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 DebianUsers
-
       # Write out the email address for each user
-      for x in DebianUsers:
+      for x in Users:
          if not Key in x[1]:
             continue
          Value = GetAttr(x, Key)
@@ -544,10 +543,10 @@ def GenMarkers(File):
       F = open(File + ".tmp", "w")
      
       # Fetch all the users
-      global DebianUsers
+      global PasswdAttrs
      
       # Write out the position for each user
-      for x in DebianUsers:
+      for x in PasswdAttrs:
          if x[1].has_key("latitude") == 0 or x[1].has_key("longitude") == 0:
             continue
          try:
@@ -570,10 +569,10 @@ def GenPrivate(File):
       F = open(File + ".tmp", "w")
      
       # Fetch all the users
-      global DebianUsers
+      global DebianDDUsers
      
       # Write out the position for each user
-      for x in DebianUsers:
+      for x in DebianDDUsers:
          if x[1].has_key("privateSub") == 0:
             continue
      
@@ -635,9 +634,9 @@ def GenMailDisable(File):
       F = open(File + ".tmp", "w")
      
       # Fetch all the users
-      global DebianUsers
+      global PasswdAttrs
      
-      for x in DebianUsers:
+      for x in PasswdAttrs:
          Reason = None
      
          if x[1].has_key("mailDisableMessage"):
@@ -665,9 +664,9 @@ def GenMailBool(File, Key):
       F = open(File + ".tmp", "w")
      
       # Fetch all the users
-      global DebianUsers
+      global PasswdAttrs
      
-      for x in DebianUsers:
+      for x in PasswdAttrs:
          Reason = None
      
          if x[1].has_key(Key) == 0:
@@ -696,9 +695,9 @@ def GenMailList(File, Key):
       F = open(File + ".tmp", "w")
      
       # Fetch all the users
-      global DebianUsers
+      global PasswdAttrs
      
-      for x in DebianUsers:
+      for x in PasswdAttrs:
          Reason = None
      
          if x[1].has_key(Key) == 0:
@@ -751,6 +750,27 @@ def GenDNS(File):
    try:
       F = open(File + ".tmp", "w")
      
+#      global HostAttrs
+#
+#      for x in HostAttrs:
+#         if x[1].has_key("hostname") == 0 or \
+#            x[1].has_key("architecture") == 0 or\
+#            x[1].has_key("sshRSAHostKey") == 0:
+#            continue
+#
+#         if IsDebianHost.match(GetAttr(x, "hostname")) is not None:
+#            continue
+#
+#         DNSInfo = ExtractDNSInfo(x)
+#         start = True
+#         for Line in DNSInfo:
+#            if start == True:
+#               Line = "%s.\t%s" % (GetAttr(x, "hostname"), Line)
+#               start = False
+#            else:
+#               Line = "\t\t\t%s" % (Line)
+#            F.write(Line + "\n")
+
       # Fetch all the users
       global PasswdAttrs
      
@@ -798,35 +818,75 @@ def GenDNS(File):
       raise
    Done(File, F, None)
 
-# Generate the DNS SSHFP records
-def GenSSHFP(File):
+def ExtractDNSInfo(x):
+
+   TTLprefix="\t"
+   if 'dnsTTL' in x[1]:
+      TTLprefix="%s\t"%(x[1]["dnsTTL"][0])
+
+   DNSInfo = []
+   if x[1].has_key("ipHostNumber"):
+      for I in x[1]["ipHostNumber"]:
+         if IsV6Addr.match(I) != None:
+            DNSInfo.append("%sIN\tAAAA\t%s" % (TTLprefix, I))
+         else:
+            DNSInfo.append("%sIN\tA\t%s" % (TTLprefix, I))
+
+   Host = GetAttr(x, "hostname")
+   Arch = GetAttr(x, "architecture")
+   Algorithm = None
+
+   for I in x[1]["sshRSAHostKey"]:
+      Split = I.split()
+      if Split[0] == 'ssh-rsa':
+         Algorithm = 1
+      if Split[0] == 'ssh-dss':
+         Algorithm = 2
+      if Algorithm == None:
+         continue
+      Fingerprint = sha.new(base64.decodestring(Split[1])).hexdigest()
+      DNSInfo.append("%sIN\tSSHFP\t%u 1 %s" % (TTLprefix, Algorithm, Fingerprint))
+
+   Mach = ""
+   if x[1].has_key("machine"):
+      Mach = " " + GetAttr(x, "machine")
+   DNSInfo.append("%sIN\tHINFO\t\"%s%s\" \"%s\"" % (TTLprefix, Arch, Mach, "Debian GNU/Linux"))
+
+   if x[1].has_key("mXRecord"):
+      for I in x[1]["mXRecord"]:
+         DNSInfo.append("%sIN\tMX\t%s" % (TTLprefix, I))
+
+   return DNSInfo
+
+# Generate the DNS records
+def GenZoneRecords(File):
    F = None
    try:
       F = open(File + ".tmp", "w")
-     
+
       # Fetch all the hosts
       global HostAttrs
-      if HostAttrs == None:
-         raise UDEmptyList, "No Hosts"
-     
+
       for x in HostAttrs:
          if x[1].has_key("hostname") == 0 or \
+            x[1].has_key("architecture") == 0 or\
             x[1].has_key("sshRSAHostKey") == 0:
             continue
-         Host = GetAttr(x, "hostname")
-         Algorithm = None
-         for I in x[1]["sshRSAHostKey"]:
-            Split = I.split()
-            if Split[0] == 'ssh-rsa':
-               Algorithm = 1
-            if Split[0] == 'ssh-dss':
-               Algorithm = 2
-            if Algorithm == None:
-               continue
-            Fingerprint = sha.new(base64.decodestring(Split[1])).hexdigest()
-            Line = "%s. IN SSHFP %u 1 %s" % (Host, Algorithm, Fingerprint)
-            Line = Sanitize(Line) + "\n"
-            F.write(Line)
+
+         if IsDebianHost.match(GetAttr(x, "hostname")) is None:
+            continue
+
+         DNSInfo = ExtractDNSInfo(x)
+         start = True
+         for Line in DNSInfo:
+            if start == True:
+               Line = "%s.\t%s" % (GetAttr(x, "hostname"), Line)
+               start = False
+            else:
+               Line = "\t\t\t%s" % (Line)
+
+            F.write(Line + "\n")
+
    # Oops, something unspeakable happened.
    except:
       Die(File, F, None)
@@ -840,10 +900,10 @@ def GenBSMTP(File, HomePrefix):
       F = open(File + ".tmp", "w")
      
       # Fetch all the users
-      global DebianUsers
+      global PasswdAttrs
      
       # Write out the zone file entry for each user
-      for x in DebianUsers:
+      for x in PasswdAttrs:
          if x[1].has_key("dnsZoneEntry") == 0:
             continue
      
@@ -874,26 +934,17 @@ def GenBSMTP(File, HomePrefix):
       raise
    Done(File, F, None)
   
-#  cache IP adresses
-HostToIPCache = {}
-def HostToIP(Host):
-   global HostToIPCache
-   if not Host in HostToIPCache:
-      IPAdressesT = None
-      try:
-         IPAdressesT = list(set([ (a[0], a[4][0]) for a in socket.getaddrinfo(Host, None)]))
-      except socket.gaierror, (code):
-         if code[0] != -2:
-            raise
-      IPAdresses = []
-      if not IPAdressesT is None:
-         for addr in IPAdressesT:
-            if addr[0] == socket.AF_INET:
-               IPAdresses += [addr[1], "::ffff:"+addr[1]]
-            else:
-               IPAdresses += [addr[1]]
-      HostToIPCache[Host] = IPAdresses
-   return HostToIPCache[Host]
+def HostToIP(Host, mapped=True):
+
+   IPAdresses = []
+
+   if Host[1].has_key("ipHostNumber"):
+      for addr in Host[1]["ipHostNumber"]:
+         IPAdresses.append(addr)
+         if IsV6Addr.match(addr) is None and mapped == "True":
+            IPAdresses.append("::ffff:"+addr)
+
+   return IPAdresses
 
 # Generate the ssh known hosts file
 def GenSSHKnown(File, mode=None):
@@ -904,8 +955,6 @@ def GenSSHKnown(File, mode=None):
       os.umask(OldMask)
      
       global HostAttrs
-      if HostAttrs is None:
-         raise UDEmptyList, "No Hosts"
      
       for x in HostAttrs:
          if x[1].has_key("hostname") == 0 or \
@@ -937,10 +986,13 @@ def GenSSHKnown(File, mode=None):
      
          for I in x[1]["sshRSAHostKey"]:
             if mode and mode == 'authorized_keys':
-               Line = 'command="rsync --server --sender -pr . /var/cache/userdir-ldap/hosts/%s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,from="%s" %s' % (Host, ",".join(HostToIP(Host)), I)
+               hosts = HostToIP(x)
+               if 'sshdistAuthKeysHost' in x[1]:
+                  hosts += x[1]['sshdistAuthKeysHost']
+               Line = 'command="rsync --server --sender -pr . /var/cache/userdir-ldap/hosts/%s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,from="%s" %s' % (Host, ",".join(hosts), I)
                #Line = 'command="rsync --server --sender -pr . /var/cache/userdir-ldap/hosts/%s",no-port-forwarding,no-X11-forwarding,no-agent-forwarding %s' % (Host,I)
             else:
-               Line = "%s %s" %(",".join(HostNames + HostToIP(Host)), I)
+               Line = "%s %s" %(",".join(HostNames + HostToIP(x, False)), I)
             Line = Sanitize(Line) + "\n"
             F.write(Line)
    # Oops, something unspeakable happened.
@@ -950,40 +1002,32 @@ def GenSSHKnown(File, mode=None):
    Done(File, F, None)
 
 # Generate the debianhosts file (list of all IP addresses)
-def GenHosts(l, File):
+def GenHosts(File):
    F = None
    try:
       OldMask = os.umask(0022)
       F = open(File + ".tmp", "w", 0644)
       os.umask(OldMask)
      
-      # Fetch all the hosts
-      hostnames = l.search_s(HostBaseDn, ldap.SCOPE_ONELEVEL, "hostname=*",
-                             ["hostname"])
-     
-      if hostnames is None:
-         raise UDEmptyList, "No Hosts"
-     
       seen = set()
-      for x in hostnames:
-         host = GetAttr(x, "hostname", None)
-         if host:
-            addrs = []
-            try:
-               addrs += socket.getaddrinfo(host, None, socket.AF_INET)
-            except socket.error:
-               pass
-            try:
-               addrs += socket.getaddrinfo(host, None, socket.AF_INET6)
-            except socket.error:
-               pass
-           
-            for addrinfo in addrs:
-               if addrinfo[0] in (socket.AF_INET, socket.AF_INET6):
-                  addr = addrinfo[4][0]
-                  if addr not in seen:
-                     print >> F, addrinfo[4][0]
-                     seen.add(addr)
+
+      global HostAttrs
+
+      for x in HostAttrs:
+
+         if IsDebianHost.match(GetAttr(x, "hostname")) is None:
+            continue
+
+         if not 'ipHostNumber' in x[1]:
+            continue
+
+         addrs = x[1]["ipHostNumber"]
+         for addr in addrs:
+            if addr not in seen:
+               seen.add(addr)
+               addr = Sanitize(addr) + "\n"
+               F.write(addr)
+
    # Oops, something unspeakable happened.
    except:
       Die(File, F, None)
@@ -1008,6 +1052,8 @@ Attrs = l.search_s(BaseDn, ldap.SCOPE_ONELEVEL, "gid=*",\
 
 # Generate the SubGroupMap and GroupIDMap
 for x in Attrs:
+   if x[1].has_key("accountStatus") and x[1]['accountStatus'] == "disabled":
+      continue
    if x[1].has_key("gidNumber") == 0:
       continue
    GroupIDMap[x[1]["gid"][0]] = int(x[1]["gidNumber"][0])
@@ -1029,23 +1075,30 @@ PasswdAttrs = l.search_s(BaseDn, ldap.SCOPE_ONELEVEL, "uid=*",\
 if PasswdAttrs is None:
    raise UDEmptyList, "No Users"
 
+PasswdAttrs.sort(lambda x, y: cmp((GetAttr(x, "uid")).lower(), (GetAttr(y, "uid")).lower()))
+
 # Fetch all the hosts
 HostAttrs    = l.search_s(HostBaseDn, ldap.SCOPE_ONELEVEL, "objectClass=debianServer",\
-                ["hostname", "sshRSAHostKey", "purpose", "allowedGroups", "exportOptions"])
+                ["hostname", "sshRSAHostKey", "purpose", "allowedGroups", "exportOptions",\
+                 "mXRecord", "ipHostNumber", "dnsTTL", "machine", "architecture"])
+
+if HostAttrs == None:
+   raise UDEmptyList, "No Hosts"
+
+HostAttrs.sort(lambda x, y: cmp((GetAttr(x, "hostname")).lower(), (GetAttr(y, "hostname")).lower()))
 
 # Generate global things
 GlobalDir = GenerateDir + "/"
 GenDisabledAccounts(GlobalDir + "disabled-accounts")
 
 PasswdAttrs = filter(lambda x: not IsRetired(x), PasswdAttrs)
-#DebianUsers = filter(lambda x: IsGidDebian(x), PasswdAttrs)
-DebianUsers = PasswdAttrs
+DebianDDUsers = filter(lambda x: IsGidDebian(x), PasswdAttrs)
 
 CheckForward()
 
 GenMailDisable(GlobalDir + "mail-disable")
-GenCDB(GlobalDir + "mail-forward.cdb", 'emailForward')
-GenCDB(GlobalDir + "mail-contentinspectionaction.cdb", 'mailContentInspectionAction')
+GenCDB(GlobalDir + "mail-forward.cdb", PasswdAttrs, 'emailForward')
+GenCDB(GlobalDir + "mail-contentinspectionaction.cdb", PasswdAttrs, 'mailContentInspectionAction')
 GenPrivate(GlobalDir + "debian-private")
 GenSSHKnown(GlobalDir+"authorized_keys", 'authorized_keys')
 GenMailBool(GlobalDir + "mail-greylist", "mailGreylisting")
@@ -1063,7 +1116,7 @@ PasswdAttrs = filter(lambda x: not x in DisabledUsers, PasswdAttrs)
 SSHFiles = GenSSHShadow()
 GenMarkers(GlobalDir + "markers")
 GenSSHKnown(GlobalDir + "ssh_known_hosts")
-GenHosts(l, GlobalDir + "debianhosts")
+GenHosts(GlobalDir + "debianhosts")
 
 for host in HostAttrs:
    if not "hostname" in host[1]:
@@ -1127,13 +1180,19 @@ for host in HostAttrs:
    DoLink(GlobalDir, OutDir, "mail-rbl")
    DoLink(GlobalDir, OutDir, "mail-rhsbl")
    DoLink(GlobalDir, OutDir, "mail-whitelist")
+   GenCDB(OutDir + "user-forward.cdb", filter(lambda x: IsInGroup(x), PasswdAttrs), 'emailForward')
+   GenCDB(OutDir + "batv-tokens.cdb", filter(lambda x: IsInGroup(x), PasswdAttrs), 'bATVToken')
+   GenCDB(OutDir + "default-mail-options.cdb", filter(lambda x: IsInGroup(x), PasswdAttrs), 'mailDefaultOptions')
 
    # Compatibility.
    DoLink(GlobalDir, OutDir, "forward-alias")
 
    if 'DNS' in ExtraList:
       GenDNS(OutDir + "dns-zone")
-      GenSSHFP(OutDir + "dns-sshfp")
+      GenZoneRecords(OutDir + "dns-sshfp")
+
+   if 'AUTHKEYS' in ExtraList:
+      DoLink(GlobalDir, OutDir, "authorized_keys")
 
    if 'BSMTP' in ExtraList:
       GenBSMTP(OutDir + "bsmtp", HomePrefix)