prototype code for sshfp generation for services
[mirror/userdir-ldap.git] / ud-generate
index 2836f5c..2951794 100755 (executable)
@@ -6,12 +6,13 @@
 #   Copyright (c) 2003-2004  James Troup <troup@debian.org>
 #   Copyright (c) 2004-2005,7  Joey Schulze <joey@infodrom.org>
 #   Copyright (c) 2001-2007  Ryan Murray <rmurray@debian.org>
-#   Copyright (c) 2008 Peter Palfrader <peter@palfrader.org>
+#   Copyright (c) 2008,2009,2010 Peter Palfrader <peter@palfrader.org>
 #   Copyright (c) 2008 Andreas Barth <aba@not.so.argh.org>
 #   Copyright (c) 2008 Mark Hymers <mhy@debian.org>
 #   Copyright (c) 2008 Luk Claes <luk@debian.org>
 #   Copyright (c) 2008 Thomas Viehmann <tv@beamnet.de>
 #   Copyright (c) 2009 Stephen Gran <steve@lobefin.net>
+#   Copyright (c) 2010 Helmut Grohne <helmut@subdivi.de>
 #
 #   This program is free software; you can redistribute it and/or modify
 #   it under the terms of the GNU General Public License as published by
 import string, re, time, ldap, getopt, sys, os, pwd, posix, socket, base64, sha, shutil, errno, tarfile, grp
 from userdir_ldap import *
 from userdir_exceptions import *
+try:
+   from cStringIO import StringIO
+except ImportError:
+   from StringIO import StringIO
 
 global Allowed
 global CurrentHost
@@ -49,6 +54,7 @@ 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(ConfModule.dns_hostmatch)
+isSSHFP = re.compile("^\s*IN\s+SSHFP")
 DNSZone = ".debian.net"
 Keyrings = ConfModule.sync_keyrings.split(":")
 
@@ -338,6 +344,8 @@ def GenSSHShadow():
       # Oops, something unspeakable happened.
       except IOError:
          Die(File, F, None)
+         # As neither masterFileName nor masterFile are defined at any point
+         # this will raise a NameError.
          Die(masterFileName, masterFile, None)
          raise
 
@@ -385,7 +393,20 @@ def GenSSHtarballs(userlist, SSHFiles, grouprevmap, target):
       to.uname = f
       to.gname = grname
       to.mode  = 0400
-      tf.addfile(to, file(os.path.join(GlobalDir, 'userkeys', f)))
+
+      contents = file(os.path.join(GlobalDir, 'userkeys', f)).read()
+      lines = []
+      for line in contents.splitlines():
+         if line.startswith("allowed_hosts=") and ' ' in line:
+            machines, line = line.split('=', 1)[1].split(' ', 1)
+            if CurrentHost not in machines.split(','):
+               continue # skip this key
+         lines.append(line)
+      if not lines:
+         continue # no keys for this host
+      contents = "\n".join(lines) + "\n"
+      to.size = len(contents)
+      tf.addfile(to, StringIO(contents))
 
    tf.close()
    os.rename(os.path.join(GlobalDir, 'ssh-keys-%s.tar.gz' % CurrentHost), target)
@@ -758,29 +779,9 @@ 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
+      RRs = {}
      
       # Write out the zone file entry for each user
       for x in PasswdAttrs:
@@ -806,11 +807,13 @@ def GenDNS(File):
                      F.write("; Has BSMTP\n")
      
                   # Write some identification information
-                  if Split[2].lower() == "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)
+                  if not RRs.has_key(Host):
+                     if Split[2].lower() in ["a", "aaaa"]:
+                        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)
+                        RRs[Host] = 1
                else:
                   Line = "; Err %s"%(str(Split))
                   F.write(Line)
@@ -894,6 +897,29 @@ def GenZoneRecords(File):
 
             F.write(Line + "\n")
 
+        # this would write sshfp lines for services on machines
+        # but we can't yet, since some are cnames and we'll make
+        # an invalid zonefile
+        #
+        # for i in x[1].get("purpose", []):
+        #    m = PurposeHostField.match(i)
+        #    if m:
+        #       m = m.group(1)
+        #       # we ignore [[*..]] entries
+        #       if m.startswith('*'):
+        #          continue
+        #       if m.startswith('-'):
+        #          m = m[1:]
+        #       if m:
+        #          if not m.endswith(HostDomain):
+        #             continue
+        #          if not m.endswith('.'):
+        #             m = m + "."
+        #          for Line in DNSInfo:
+        #             if isSSHFP.match(Line):
+        #                Line = "%s\t%s" % (m, Line)
+        #                F.write(Line + "\n")
+
    # Oops, something unspeakable happened.
    except:
       Die(File, F, None)
@@ -997,7 +1023,6 @@ def GenSSHKnown(File, mode=None):
                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(x, False)), I)
             Line = Sanitize(Line) + "\n"