# 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 = []
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)
# Write out the position for each user
for x in PasswdAttrs:
- if x[1].has_key("latitude") == 0 or x[1].has_key("longitude") == 0:
+ 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:
# Write out the position for each user
for x in DebianDDUsers:
- if x[1].has_key("privateSub") == 0:
+ 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:
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"
# 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
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")