# 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 *
+import UDLdap
+try:
+ from cStringIO import StringIO
+except ImportError:
+ from StringIO import StringIO
global Allowed
global CurrentHost
+if os.getuid() == 0:
+ sys.stderr.write("You should probably not run ud-generate as root.\n")
+ sys.exit(1)
+
PasswdAttrs = None
DebianUsers = None
DisabledUsers = []
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 (gluck)\.debian\.org\..*",re.DOTALL)
-PurposeHostField = re.compile(r"\[\[([\*\-]?[a-z0-9.\-]*)(?:\|.*)?\]\]")
+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(":")
# We'll give them a few extra days over what we said
age = 6 * 31 * 24 * 60 * 60
try:
- if (time.time() - time.mktime(time.strptime(line[1], "%Y-%m-%d"))) > age:
- return True
+ return (time.time() - time.mktime(time.strptime(line[1], "%Y-%m-%d"))) > age
except IndexError:
return False
+ except ValueError:
+ return False
return False
# See if this user is in the group list
def IsInGroup(DnRecord):
- if Allowed == None:
- return 1
+ if Allowed is None:
+ return True
# See if the primary group is in the list
if Allowed.has_key(GetAttr(DnRecord, "gidNumber")) != 0:
- return 1
+ return True
# Check the host based ACL
if DnRecord[1].has_key("allowedHost") != 0:
- for I in DnRecord[1]["allowedHost"]:
- if CurrentHost == I:
- return 1
+ if CurrentHost in DnRecord[1]["allowedHost"]:
+ return True
# See if there are supplementary groups
if DnRecord[1].has_key("supplementaryGid") == 0:
- return 0
+ return False
supgroups=[]
addGroups(supgroups, DnRecord[1]["supplementaryGid"], GetAttr(DnRecord, "uid"))
for g in supgroups:
if Allowed.has_key(g):
- return 1
- return 0
+ return True
+ return False
def Die(File, F, Fdb):
if F != None:
I = 0
for x in PasswdAttrs:
- if x[1].has_key("uidNumber") == 0 or IsInGroup(x) == 0:
+ if x[1].has_key("uidNumber") == 0 or not IsInGroup(x):
continue
# Do not let people try to buffer overflow some busted passwd parser.
I = 0
for x in PasswdAttrs:
- if x[1].has_key("uidNumber") == 0 or IsInGroup(x) == 0:
+ if x[1].has_key("uidNumber") == 0 or not IsInGroup(x):
continue
Pass = GetAttr(x, "userPassword")
for x in PasswdAttrs:
Pass = '*'
- if x[1].has_key("uidNumber") == 0 or IsInGroup(x) == 0:
+ if x[1].has_key("uidNumber") == 0 or not IsInGroup(x):
continue
if x[1].has_key('sudoPassword'):
continue
Pass = cryptedpass
if for_this_host: # this makes sure we take a per-host entry over the for-all entry
- break
+ break
if len(Pass) > 50:
Pass = '*'
# Oops, something unspeakable happened.
except IOError:
- Die(File, F, None)
- Die(masterFileName, masterFile, None)
- raise
+ Die(File, F, None)
+ # As neither masterFileName nor masterFile are defined at any point
+ # this will raise a NameError.
+ Die(masterFileName, masterFile, None)
+ raise
return userfiles
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)
# let's see if we handled this group already
if group in existingGroups:
- continue
+ continue
if not GroupIDMap.has_key(group):
print "Group", group, "does not exist but", uid, "is in it"
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 x[1].has_key("uidNumber") == 0 or IsInGroup(x) == 0:
+ 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:
continue
# 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]:
- Line = Line + ("%s%s" % (Comma, I))
- Comma = ','
+ Line = Line + ("%s%s" % (Comma, I))
+ Comma = ','
Line = Sanitize(Line) + "\n"
F.write("0%u %s" % (J, Line))
F.write(".%s %s" % (x, Line))
return grouprevmap
def CheckForward():
- global DebianUsers
- for x in DebianUsers:
+ global PasswdAttrs
+ for x in PasswdAttrs:
if x[1].has_key("emailForward") == 0:
continue
- if IsInGroup(x) == 0:
+ if not IsInGroup(x):
x[1].pop("emailForward")
continue
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
raise
Done(File, F, None)
-def GenAllForward(File):
+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:
- if x[1].has_key("emailForward") == 0:
+ for x in Users:
+ if not Key in x[1]:
continue
-
- # Do not allow people to try to buffer overflow busted parsers
- Forward = GetAttr(x, "emailForward")
-
+ Value = GetAttr(x, Key)
User = GetAttr(x, "uid")
- Fdb.write("+%d,%d:%s->%s\n" % (len(User), len(Forward), User, Forward))
-
+ Fdb.write("+%d,%d:%s->%s\n" % (len(User), len(Value), User, Value))
+
Fdb.write("\n")
# Oops, something unspeakable happened.
except:
F = open(File + ".tmp", "w")
# Fetch all the users
- global DebianUsers
+ global PasswdAttrs
# Write out the position for each user
- for x in DebianUsers:
- if x[1].has_key("latitude") == 0 or x[1].has_key("longitude") == 0:
+ for x in PasswdAttrs:
+ a = UDLdap.Account(x[0], x[1])
+ if not ('latitude' in a and 'longitude' in a):
continue
try:
- Line = "%8s %8s \"\""%(DecDegree(GetAttr(x, "latitude"), 1), DecDegree(GetAttr(x, "longitude"), 1))
+ Line = "%8s %8s \"\""%(a.latitude_dec(True), a.longitude_dec(True))
Line = Sanitize(Line) + "\n"
F.write(Line)
except:
F = open(File + ".tmp", "w")
# Fetch all the users
- global DebianUsers
+ global DebianDDUsers
# Write out the position for each user
- for x in DebianUsers:
- if x[1].has_key("privateSub") == 0:
+ for x in DebianDDUsers:
+ a = UDLdap.Account(x[0], x[1])
+ if not a.is_active_user():
continue
-
- # If the account has no PGP key, do not write it
- if x[1].has_key("keyFingerPrint") == 0:
+ if not 'privateSub' in a:
continue
-
try:
- Line = "%s"%(GetAttr(x, "privateSub"))
+ Line = "%s"%(a['privateSub'])
Line = Sanitize(Line) + "\n"
F.write(Line)
except:
I = 0
for x in PasswdAttrs:
- if x[1].has_key("uidNumber") == 0:
+ a = UDLdap.Account(x[0], x[1])
+ if a.pw_active():
continue
-
- Pass = GetAttr(x, "userPassword")
- Line = ""
- # *LK* is the reference value for a locked account
- # password starting with ! is also a locked account
- if Pass.find("*LK*") != -1 or Pass.startswith("!"):
- # Format is <login>:<reason>
- Line = "%s:%s" % (GetAttr(x, "uid"), "Account is locked")
-
- if Line != "":
- F.write(Sanitize(Line) + "\n")
-
+ Line = "%s:%s" % (a['uid'], "Account is locked")
DisabledUsers.append(x)
-
+ F.write(Sanitize(Line) + "\n")
+
# Oops, something unspeakable happened.
except:
Die(File, F, None)
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"):
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:
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:
Line = None
for z in x[1][Key]:
if Key == "mailWhitelist":
- if re.match('^[-\w.]+(/[\d]+)?$', z) == None:
- continue
+ if re.match('^[-\w.]+(/[\d]+)?$', z) == None:
+ continue
else:
- if re.match('^[-\w.]+$', z) == None:
- continue
+ if re.match('^[-\w.]+$', z) == None:
+ continue
if found == 0:
- found = 1
- Line = GetAttr(x, "uid")
+ found = 1
+ Line = GetAttr(x, "uid")
else:
Line += " "
Line += ": " + z
if Key == "mailRHSBL":
- Line += "/$sender_address_domain"
+ Line += "/$sender_address_domain"
if Line != None:
- Line = Sanitize(Line) + "\n"
- F.write(Line)
+ Line = Sanitize(Line) + "\n"
+ F.write(Line)
except:
pass
return False
# Generate the DNS Zone file
-def GenDNS(File, HomePrefix):
+def GenDNS(File):
F = None
try:
F = open(File + ".tmp", "w")
# Fetch all the users
global PasswdAttrs
+ RRs = {}
# Write out the zone file entry for each user
for x in PasswdAttrs:
Host = Split[0] + DNSZone
if BSMTPCheck.match(Line) != None:
- F.write("; Has BSMTP\n")
+ 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)
raise
Done(File, F, None)
-# Generate the DNS SSHFP records
-def GenSSHFP(File, HomePrefix):
+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))
+
+ Algorithm = None
+
+ 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))
+
+ 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"]:
+ 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("sshRSAHostKey") == 0:
+ if x[1].has_key("hostname") == 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")
+
+ # 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)
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
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):
os.umask(OldMask)
global HostAttrs
- if HostAttrs == None:
- raise UDEmptyList, "No Hosts"
for x in HostAttrs:
if x[1].has_key("hostname") == 0 or \
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(HNames + HostToIP(Host)), 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)
+ 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)
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.
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 == 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)
- raise
+ Die(File, F, None)
+ raise
Done(File, F, None)
def GenKeyrings(OutDir):
for k in Keyrings:
shutil.copy(k, OutDir)
-
# Connect to the ldap server
l = connectLDAP()
-F = open(PassDir + "/pass-" + pwd.getpwuid(os.getuid())[0], "r")
-Pass = F.readline().strip().split(" ")
-F.close()
+# for testing purposes it's sometimes useful to pass username/password
+# via the environment
+if 'UD_CREDENTIALS' in os.environ:
+ Pass = os.environ['UD_CREDENTIALS'].split()
+else:
+ F = open(PassDir + "/pass-" + pwd.getpwuid(os.getuid())[0], "r")
+ Pass = F.readline().strip().split(" ")
+ F.close()
l.simple_bind_s("uid=" + Pass[0] + "," + BaseDn, Pass[1])
# Fetch all the groups
# 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])
SubGroupMap.setdefault(x[1]["gid"][0], []).extend(x[1]["subGroup"])
# Fetch all the users
-PasswdAttrs = l.search_s(BaseDn, ldap.SCOPE_ONELEVEL, "uid=*",\
+PasswdAttrs = l.search_s(BaseDn, ldap.SCOPE_ONELEVEL, "(&(uid=*)(!(uidNumber=0)))",\
["uid", "uidNumber", "gidNumber", "supplementaryGid",\
"gecos", "loginShell", "userPassword", "shadowLastChange",\
"shadowMin", "shadowMax", "shadowWarning", "shadowInactive",
"allowedHost", "sshRSAAuthKey", "dnsZoneEntry", "cn", "sn",\
"keyFingerPrint", "privateSub", "mailDisableMessage",\
"mailGreylisting", "mailCallout", "mailRBL", "mailRHSBL",\
- "mailWhitelist", "sudoPassword", "objectClass", "accountStatus"])
+ "mailWhitelist", "sudoPassword", "objectClass", "accountStatus",\
+ "mailContentInspectionAction"])
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, "sshRSAHostKey=*",\
- ["hostname", "sshRSAHostKey", "purpose"])
+HostAttrs = l.search_s(HostBaseDn, ldap.SCOPE_ONELEVEL, "objectClass=debianServer",\
+ ["hostname", "sshRSAHostKey", "purpose", "allowedGroups", "exportOptions",\
+ "mXRecord", "ipHostNumber", "dnsTTL", "machine", "architecture"])
-# Open the control file
-if len(sys.argv) == 1:
- F = open(GenerateConf, "r")
-else:
- F = open(sys.argv[1], "r")
+if HostAttrs == None:
+ raise UDEmptyList, "No Hosts"
+
+HostAttrs.sort(lambda x, y: cmp((GetAttr(x, "hostname")).lower(), (GetAttr(y, "hostname")).lower()))
+
+# override globaldir for testing
+if 'UD_GENERATEDIR' in os.environ:
+ GenerateDir = os.environ['UD_GENERATEDIR']
# Generate global things
GlobalDir = GenerateDir + "/"
GenDisabledAccounts(GlobalDir + "disabled-accounts")
-PasswdAttrs = filter(not IsRetired, PasswdAttrs)
-DebianUsers = filter(IsGidDebian, PasswdAttrs)
+PasswdAttrs = filter(lambda x: not IsRetired(x), PasswdAttrs)
+DebianDDUsers = filter(lambda x: IsGidDebian(x), PasswdAttrs)
CheckForward()
GenMailDisable(GlobalDir + "mail-disable")
-GenAllForward(GlobalDir + "mail-forward.cdb")
+GenCDB(GlobalDir + "mail-forward.cdb", PasswdAttrs, 'emailForward')
+GenCDB(GlobalDir + "mail-contentinspectionaction.cdb", PasswdAttrs, 'mailContentInspectionAction')
GenPrivate(GlobalDir + "debian-private")
-#GenSSHKnown(l,GlobalDir+"authorized_keys", 'authorized_keys')
+GenSSHKnown(GlobalDir+"authorized_keys", 'authorized_keys')
GenMailBool(GlobalDir + "mail-greylist", "mailGreylisting")
GenMailBool(GlobalDir + "mail-callout", "mailCallout")
GenMailList(GlobalDir + "mail-rbl", "mailRBL")
SSHFiles = GenSSHShadow()
GenMarkers(GlobalDir + "markers")
GenSSHKnown(GlobalDir + "ssh_known_hosts")
-GenHosts(l, GlobalDir + "debianhosts")
-
-while(1):
- Line = F.readline()
- if Line == "":
- break
- Line = Line.strip()
- if Line == "":
- continue
- if Line[0] == '#':
+GenHosts(GlobalDir + "debianhosts")
+
+for host in HostAttrs:
+ if not "hostname" in host[1]:
continue
- Split = Line.split(" ")
- OutDir = GenerateDir + '/' + Split[0] + '/'
+ CurrentHost = host[1]['hostname'][0]
+ OutDir = GenerateDir + '/' + CurrentHost + '/'
try:
os.mkdir(OutDir)
except:
# Get the group list and convert any named groups to numerics
GroupList = {}
+ for groupname in AllowedGroupsPreload.strip().split(" "):
+ GroupList[groupname] = True
+ if 'allowedGroups' in host[1]:
+ for groupname in host[1]['allowedGroups']:
+ GroupList[groupname] = True
+ for groupname in GroupList.keys():
+ if groupname in GroupIDMap:
+ GroupList[str(GroupIDMap[groupname])] = True
+
ExtraList = {}
- for I in Split[2:]:
- if I[0] == '[':
- ExtraList[I] = None
- continue
- GroupList[I] = None
- if GroupIDMap.has_key(I):
- GroupList[str(GroupIDMap[I])] = None
+ if 'exportOptions' in host[1]:
+ for extra in host[1]['exportOptions']:
+ ExtraList[extra.upper()] = True
Allowed = GroupList
if Allowed == {}:
- Allowed = None
- CurrentHost = Split[0]
+ Allowed = None
DoLink(GlobalDir, OutDir, "debianhosts")
DoLink(GlobalDir, OutDir, "ssh_known_hosts")
DoLink(GlobalDir, OutDir, "disabled-accounts")
sys.stdout.flush()
- if ExtraList.has_key("[NOPASSWD]"):
- userlist = GenPasswd(OutDir + "passwd", Split[1], "*")
+ if 'NOPASSWD' in ExtraList:
+ userlist = GenPasswd(OutDir + "passwd", HomePrefix, "*")
else:
- userlist = GenPasswd(OutDir + "passwd", Split[1], "x")
+ userlist = GenPasswd(OutDir + "passwd", HomePrefix, "x")
sys.stdout.flush()
grouprevmap = GenGroup(OutDir + "group")
- GenShadowSudo(OutDir + "sudo-passwd", ExtraList.has_key("[UNTRUSTED]") or ExtraList.has_key("[NOPASSWD]"))
+ GenShadowSudo(OutDir + "sudo-passwd", ('UNTRUSTED' in ExtraList) or ('NOPASSWD' in ExtraList))
# Now we know who we're allowing on the machine, export
# the relevant ssh keys
GenSSHtarballs(userlist, SSHFiles, grouprevmap, os.path.join(OutDir, 'ssh-keys.tar.gz'))
- if ExtraList.has_key("[UNTRUSTED]"):
- print "[UNTRUSTED] tag is obsolete and may be removed in the future."
- continue
- if not ExtraList.has_key("[NOPASSWD]"):
+ if not 'NOPASSWD' in ExtraList:
GenShadow(OutDir + "shadow")
# Link in global things
- if not ExtraList.has_key("[NOMARKERS]"):
+ if not 'NOMARKERS' in ExtraList:
DoLink(GlobalDir, OutDir, "markers")
DoLink(GlobalDir, OutDir, "mail-forward.cdb")
+ DoLink(GlobalDir, OutDir, "mail-contentinspectionaction.cdb")
DoLink(GlobalDir, OutDir, "mail-disable")
DoLink(GlobalDir, OutDir, "mail-greylist")
DoLink(GlobalDir, OutDir, "mail-callout")
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 ExtraList.has_key("[DNS]"):
- GenDNS(OutDir + "dns-zone", Split[1])
- GenSSHFP(OutDir + "dns-sshfp", Split[1])
+ if 'DNS' in ExtraList:
+ GenDNS(OutDir + "dns-zone")
+ GenZoneRecords(OutDir + "dns-sshfp")
+
+ if 'AUTHKEYS' in ExtraList:
+ DoLink(GlobalDir, OutDir, "authorized_keys")
- if ExtraList.has_key("[BSMTP]"):
- GenBSMTP(OutDir + "bsmtp", Split[1])
+ if 'BSMTP' in ExtraList:
+ GenBSMTP(OutDir + "bsmtp", HomePrefix)
- if ExtraList.has_key("[PRIVATE]"):
+ if 'PRIVATE' in ExtraList:
DoLink(GlobalDir, OutDir, "debian-private")
- if ExtraList.has_key("[KEYRING]"):
+ if 'KEYRING' in ExtraList:
for k in Keyrings:
DoLink(GlobalDir, OutDir, os.path.basename(k))
else: