# 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
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$")
+IsDebianHost = re.compile(ConfModule.dns_hostmatch)
+isSSHFP = re.compile("^\s*IN\s+SSHFP")
DNSZone = ".debian.net"
Keyrings = ConfModule.sync_keyrings.split(":")
# 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
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)
GroupMap = {}
for x in GroupIDMap.keys():
GroupMap[x] = []
+ GroupHasPrimaryMembers = {}
# Fetch all the users
global PasswdAttrs
# Sort them into a list of groups having a set of users
for x in PasswdAttrs:
uid = GetAttr(x, "uid")
+ if 'gidNumber' in x[1]:
+ GroupHasPrimaryMembers[ int(x[1]["gidNumber"][0]) ] = True
if x[1].has_key("uidNumber") == 0 or not IsInGroup(x):
continue
if x[1].has_key("supplementaryGid") == 0:
# Output the group file.
J = 0
for x in GroupMap.keys():
- grouprevmap[GroupIDMap[x]] = x
if GroupIDMap.has_key(x) == 0:
continue
+
+ if len(GroupMap[x]) == 0 and GroupIDMap[x] not in GroupHasPrimaryMembers:
+ continue
+
+ grouprevmap[GroupIDMap[x]] = x
+
Line = "%s:x:%u:" % (x, GroupIDMap[x])
Comma = ''
for I in GroupMap[x]:
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:
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)
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))
+ if 'sshRSAHostKey' in x[1]:
+ 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 'architecture' in x[1]:
+ Arch = GetAttr(x, "architecture")
+ 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"]:
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:
+ if x[1].has_key("hostname") == 0:
continue
if IsDebianHost.match(GetAttr(x, "hostname")) is None:
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)
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"
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")